/**Coodo Bootstrap组件
 * version: dev
 * update author:wuzh
 * create data:2015-11-30
 * update date:update at any time
 */
//parser
+function ($) {
    $.parser = {
        auto: true,
        plugins: ['layout','panel', 'grid', 'navbar', 'tabs', 'accordion', 'dialog','linkButton','selectPicker', 'autoComplete', 'comboArea', 'treeView'],
        parse: function (target) {
            //var aa = [];
            for (var i = 0; i < $.parser.plugins.length; i++) {
                var item = $.parser.plugins[i];

                if (target && target.eq(0).hasClass("coodo-" + item))
                    this.initPlugin(target.eq(0), item);

                var r = $(".coodo-" + item, target);
                if (r.length)
                    this.initPlugin(r, item);
            }
        },
        initPlugin: function (target, item) {
            if (target[item])
                target[item]();
        },
        parseOptions: function (target) {
            var t = $(target);
            var _8 = {};
            var s = $.trim(t.attr("data-options"));
            if (s) {
                var _9 = s.substring(0, 1);
                var _a = s.substring(s.length - 1, 1);
                if (_9 != "{") {
                    s = "{" + s;
                }
                if (_a != "}") {
                    s = s + "}";
                }
                _8 = (new Function("return " + s))();
            }

            return _8;
        }
    };
    $(function () {
        if ($.parser.auto)
            $.parser.parse();
    });

    $.getGuid = function () {
        var G = function () {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        };

        var guid = (G() + G() + "-" + G() + "-" + G() + "-" + G() + "-" + G() + G() + G());

        return guid.replace(/[-]/g, '').toUpperCase();
    };
    $.parseBool = function (v) {
        if (typeof v == "string")
            return !!v.toLowerCase().replace(/false/g, '');
        else
            return false;
    };
    //自定义扩展函数，用于搜索
    $.expr[':'].icontains = function (obj, index, meta) {
        return $(obj).text().toUpperCase().indexOf(meta[3].toUpperCase()) >= 0;
    }
}(jQuery);
//mask
+function ($) {
    function setMask(target, mask, maskInfo) {
        var w = $(target).width();
        var h = $(target).height();
        if (target != window) {
            w += (+$(target).css('padding-left').replace('px', ''))
                + (+$(target).css('padding-right').replace('px', ''))
                + (+$(target).css('border-left-width').replace('px', '') || 0)
                + (+$(target).css('border-right-width').replace('px', '') || 0);
            h += (+$(target).css('padding-top').replace('px', ''))
                + (+$(target).css('padding-bottom').replace('px', ''))
                + (+$(target).css('border-top-width').replace('px', '') || 0)
                + (+$(target).css('border-bottom-width').replace('px', '') || 0);

            var radius = $(target).css('border-radius');
            if (radius && +radius.replace('px', ''))
                mask.css('border-radius', radius);
        }

        mask.width(w);
        mask.height(h);
        //mask.css('line-height', h);
        var offset = $(target).offset() || {top: 0, left: 0};
        mask.offset(offset);
        maskInfo.offset({top: mask.offset().top + h / 2 - 10, left: mask.offset().left + (w - maskInfo.width()) / 2});
    }

    $.fn.openMask = function (options) {
        return this.each(function () {
            var option = $.extend({}, $.fn.maskDefault, options || {});
            var maskId = $(this).attr('maskId');

            var mask;
            var maskInfo;
            if (maskId) {
                mask = $('#mask-' + maskId.id);
                maskInfo = $('#maskInfo-' + maskId.id);
            }
            else {
                $(this).attr('maskId', maskId = $.getGuid());
            }
            if (!mask || !mask.length) {
                mask = $('<div class="coodo-mask text-center" />').attr('id', "mask-" + maskId);
                maskInfo = $('<div class="coodo-maskInfo" />').attr('id', 'maskInfo-' + maskId);
                if (option.iconCls) maskInfo.append($('<i/>').addClass(option.iconCls));
                if (option.msg) maskInfo.append("&nbsp;" + option.msg);
                if (this == window || $(this).is('body')) {
                    $('body').append(mask);
                    $('body').append(maskInfo);
                }
                else {
                    $(this).after(mask).after(maskInfo);
                }
            }
            setMask(this, mask, maskInfo);
            if (this == window)
                $('body').addClass('coodo-openMask');
            else
                $(this).addClass('coodo-openMask');

            var that = this;
            $(window).on('resize.' + maskId, function () {
                setMask(that, mask, maskInfo);
            });
        });
    };
    $.fn.resizeMask = function () {
        var target = this[0];
        var maskId = $(target).attr('maskId');
        var mask;
        var maskInfo;
        if (maskId) {
            mask = $('#mask-' + maskId);
            maskInfo = $('#maskInfo-' + maskId);
            if (mask.length && maskInfo.length)
                setMask(target, mask, maskInfo);
        }
    };
    $.fn.closeMask = function () {
        return this.each(function () {
            var maskId = $(this).attr('maskId');
            if (maskId) {
                $('#mask-' + maskId + ",#maskInfo-" + maskId).remove();
            }
            if (this == window)
                $('body').removeClass('coodo-openMask');
            else
                $(this).removeClass('coodo-openMask');

            $(this).off('.mask').removeAttr('maskId');
            $(window).off('.' + maskId);
        });
    };
    $.fn.maskDefault = {
        iconCls: 'coodo-loading', msg: 'loading...'
    };
}(jQuery);
//pagination
+function ($) {
    function init(target) {
        var opts = $(target).data('pagination').options;
        createPagination(target);
        initEvent(target);
        if (opts.total) {
            buildPageNumber(target, 1, opts.total);
        }
        updatePagerInfo(target);
        $(target).addClass('row coodo-pagination');
    }

    function initEvent(target) {
        var state = $.data(target, 'pagination');
        var opts = state.options;
        var pageSel = $(target).find('>.pageSelect>.pagination');

        $(target).off('.pagination')
            .on('click.pagination', '.pagination>li>a[aria-label="Home"]', function () {
                if ($(this).parent().hasClass('disabled')) return;
                opts.pageNumber = 1;
                var homePage = pageSel.find('>li:has(a[pageNumber=1][aria-label="Normal"])');
                pageSel.find('li.active').removeClass('active');
                if (homePage.length) {
                    homePage.addClass('active');
                }
                else {
                    buildPageNumber(target, 1, opts.total);
                }
                updatePagerInfo(target);
                opts.onSelectPage.call(this, $(this).attr('pageNumber'), opts.pageSize);
            }) //home
            .on('click.pagination', '.pagination>li>a[aria-label="End"]', function () {
                if ($(this).parent().hasClass('disabled')) return;
                var totalPage = Math.ceil(opts.total / opts.pageSize);
                var endPage = pageSel.find('li:has(a[pageNumber=' + totalPage + '][aria-label="Normal"])');
                if (endPage.length) {
                    pageSel.find('li.active').removeClass('active');
                    endPage.addClass('active');
                }
                else {
                    var k = totalPage > opts.showPage ? (Math.ceil(totalPage / opts.showPage) - 1) * opts.showPage + 1 : 1;
                    buildPageNumber(target, k, opts.total);
                    pageSel.find('li.active').removeClass('active');
                    pageSel.find('li:has(a[pageNumber=' + totalPage + '][aria-label="Normal"])').addClass('active');
                }
                opts.pageNumber = totalPage;
                updatePagerInfo(target);
                opts.onSelectPage.call(this, $(this).attr('pageNumber'), opts.pageSize);
            })//end
            .on('click.pagination', '.pagination>li>a[aria-label="More"]', function () {
                opts.pageNumber = +$(this).attr('pageNumber');
                buildPageNumber(target, opts.pageNumber, opts.total);
                updatePagerInfo(target);
                opts.onSelectPage.call(this, $(this).attr('pageNumber'), opts.pageSize);
            }) //more
            .on('click.pagination', '.pagination>li>a[aria-label="Normal"]', function (e) {
                var _curPageNumber = $(this).attr('pageNumber');
                if (opts.pageNumber == _curPageNumber) return;

                opts.pageNumber = _curPageNumber;
                pageSel.find("li.active").removeClass("active");
                $(this).parent().addClass("active");
                updatePagerInfo(target);
                opts.onSelectPage.call(this, opts.pageNumber, opts.pageSize);
            }); //normal
    }

    function createPagination(target) {
        var opts = $.data(target, 'pagination').options;

        if (!$(target).find('.pageInfo,.pageSelect').length) {
            var pageInfo = $('<div class="col-md-4 pageInfo">提示信息</div>');
            var pageSel = $('<div class="col-md-8 pageSelect"/>');
            $('<ul class="pagination"/>')
                .append('<li class="disabled"><a  aria-label="Home" pageNumber="1"><span class="glyphicon glyphicon-step-backward" aria-hidden="true"/></a></li>')
                .append('<li><a aria-label="End"><span class="glyphicon glyphicon-step-forward" aria-hidden="true"/></a></li>')
                .appendTo(pageSel);

            $(target).append(pageInfo).append(pageSel);
        }
    }

    function buildPageNumber(target, beginPage, total) {

        var state = $.data(target, 'pagination');
        var opts = state.options;
        opts.pageNumber = beginPage || 1;
        opts.total = total || 0;
        var totalPage = state.totalPage = Math.ceil(opts.total / opts.pageSize); //计算总页数
        var pageTool = $(target).find(".pageSelect>.pagination");//分页控件

        pageTool.find('li:has(a[aria-label!="Home"][aria-label!="End"])').remove(); //清除现在页码
        var markBit = pageTool.children(':eq(0)');

        var step = beginPage + opts.showPage - 1;
        step = step > totalPage ? totalPage : step;

        //后.更多
        if (step < totalPage)
            markBit.after('<li><a aria-label="More" pageNumber="' + (step + 1) + '">...</a></li>');

        for (var i = step; i >= beginPage; i--)
            markBit = markBit.after('<li><a aria-label="Normal" pageNumber="' + i + '">' + i + '</a></li>');

        //前.更多
        if (beginPage > 1)
            markBit.after('<li><a aria-label="More" pageNumber="' + (beginPage - opts.showPage) + '">...</a></li>');

        pageTool.find('>li>a[aria-label="End"]').attr('pageNumber', totalPage);
        pageTool.find('>li:has(a[aria-label="Normal"]):eq(0)').addClass('active');
    }

    function updatePagerInfo(target) {
        var state = $.data(target, 'pagination');
        var opts = state.options;

        var pagerInfo = $(target).find(".pageInfo"); //分页提示信息

        var begin = (opts.pageNumber - 1) * opts.pageSize + 1;
        var end = opts.pageNumber * opts.pageSize;
        end = end > opts.total ? opts.total : end;
        if (!opts.total)
            begin = end = 0;

        var info = opts.displayMsg
            .replace('{from}', begin)
            .replace('{to}', end)
            .replace('{total}', opts.total);

        pagerInfo.html(info);

        updatePageNumberState(target);
    }

    function updatePageNumberState(target) {
        var state = $.data(target, 'pagination');
        var opts = state.options;

        var home = $(target).find('.pagination>li:has(a[aria-label="Home"])');
        var end = $(target).find('.pagination>li:has(a[aria-label="End"])');
        if (opts.pageNumber == 1) home.addClass('disabled'); else home.removeClass('disabled');
        if (opts.pageNumber == state.totalPage) end.addClass('disabled'); else end.removeClass('disabled');
    }

    $.fn.pagination = function (options, param) {
        if (typeof options == 'string') {
            return $.fn.pagination.methods[options](this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('pagination');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'pagination', {
                    options: $.extend({}, $.fn.pagination.defaults, $.parser.parseOptions(this), option),
                    totalPage: 0
                });
            init(this);
        });
    };
    $.fn.pagination.methods = {
        options: function (jq) {
            return $.data(jq[0], 'pagination').options;
        },
        build: function (jq, total) {
            return jq.each(function () {
                buildPageNumber(this, 1, total);
                updatePagerInfo(this);
            });
        }
    };
    $.fn.pagination.defaults = {
        total: 0,
        pageSize: 10,
        pageNumber: 1,
        showPage: 5,
        displayMsg: '显示 {from} 至 {to} 项，共 {total} 项',
        onSelectPage: function (pageNumber, pageSize) {
        }
    };
}(jQuery);
//drag
+function ($) {
    function init(target) {
        startDrag(target);
    }

    function startDrag(target) {
        var state = $.data(target, 'drag');
        var opts = state.options;

        //handle实际触发拖动的对象
        state.handle = opts.handle ? (typeof opts.handle == 'string' ? $(opts.handle, target) : opts.handle) : $(target);

        state.handle.css('cursor', opts.cursor)
            .off('.drag')
            .on('mousedown.drag', function (e) {
                if (e.which == 2 || e.which == 3) return;
                if (opts.onBeforeDrag.call(target, e) == false) return;

                var targetOffset = $(target).offset();
                var offsetX = e.pageX - targetOffset.left, offsetY = e.pageY - targetOffset.top;
                if (opts.proxy) {
                    if (typeof opts.proxy == "function")
                        state.proxy = opts.proxy.call(target);//如果为一个函数，则调用这个函数返回值
                    else if (opts.proxy == "clone")
                        state.proxy = $(target).clone()
                            .width($(target).outerWidth())
                            .height($(target).outerHeight())
                            .removeAttr('id')
                            .css({position: 'absolute', opacity: '0.5'})
                            .insertAfter(target)
                            .offset(targetOffset);//复制当前dom,并插到当前dom后面
                    else {
                        var tmp = $(opts.proxy);
                        state = tmp.length ? tmp : null;
                    }
                } else {
                    state.proxy = $(target);
                }
                state.proxy.css('z-index', 9999);

                $(document)
                    .off('.drag')
                    .on('mousedown.drag', function (e) {
                        opts.onStartDrag.call(target, e);
                    })
                    .on('mousemove.drag', {proxy: state.proxy, left: 0, top: 0}, function (e) {
                        $('body').on('selectstart', function () {
                            return false;
                        }).addClass('disabledSelect');
                        e.data.left = e.pageX - offsetX + (opts.deltaX || 0);
                        e.data.top = e.pageY - offsetY + (opts.deltaY || 0);
                        if (opts.onDrag.call(target, e) == false) return;

                        var pos = {left: e.data.left, top: e.data.top};

                        if (opts.axis) {
                            if (opts.axis == 'v')
                                delete pos.left;
                            else if (opts.axis == "h")
                                delete pos.top;
                        }
                        state.proxy.offset(pos);
                    })
                    .on('mouseup.drag', function (e) {
                        state.proxy.css('z-index', 'auto');
                        if (opts.onStopDrag.call(target, e) == false) {
                            $(target).animate({left: '', top: ''});
                        }
                        else if (target != state.proxy[0]) {
                            $(target).offset(state.proxy.offset());
                        }
                        if (opts.proxy)
                            state.proxy.remove();
                        stopDrag(target);
                    });
            });
    }

    function stopDrag(target) {
        var state = $(target).data('drag');
        var opts = state.options;
        $('body').off('selectstart').removeClass('disabledSelect');
        $(document).off('.drag');
    }

    function disableDrag(target) {
        var state = $(target).data('drag');
        state.handle.css('cursor', 'default').off('.drag');
        stopDrag(target);
    }

    $.fn.drag = function (options) {
        if (typeof options == "string") {
            var method = $.fn.drag.methods[options];
            if (method) return method(this);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('drag');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "drag", {
                    options: $.extend({}, $.fn.drag.defaults, $.parser.parseOptions(this), option),
                    handle: null,
                    proxy: null
                });
            init(this);
        });
    };
    $.fn.drag.methods = {
        options: function (jq) {
            return $.data(jq[0], 'drag').options;
        },
        proxy: function (jq) {
            var state = $.data(jq[0], 'drag');
            if (state.options.proxy)
                return state.proxy;
            else
                return null;
        },
        enable: function (jq) {
            return jq.each(function () {
                startDrag(this);
            });
        },
        disable: function (jq) {
            return jq.each(function () {
                disableDrag(this);
            });
        }
    };
    $.fn.drag.defaults = {
        handle: undefined,
        proxy: undefined,
        cursor: 'move',
        deltaX: undefined,
        deltaY: undefined,
        axis: undefined,
        onBeforeDrag: function (e) {
        },
        onStartDrag: function (e) {
        },
        onDrag: function (e) {
        },
        onStopDrag: function (e) {
        }
    }
}(jQuery);
//linkButton
+function ($) {

    function init(target) {
        $(target).addClass('coodo-linkButton');
        initAttr(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'linkButton').options;
        var btn = $(target);

        if (btn.is('a')) {
            btn.attr('role', 'button');
            btn.attr('href', '#');
        }
        if (opts.url && opts.goal) {
            var winDialog = $(opts.goal);
            if (!winDialog.length)
                winDialog = $.dialog.create($.extend({}, opts, {id: opts.goal.replace('#', '')}));
            else {
                var winOpts = winDialog.dialog('options');
                if (winOpts) $.extend(winOpts, opts, {id: opts.goal.replace('#', '')});
            }

            btn.off('click').click(function () {
                winDialog.dialog('open');
            });
        }
    }

    $.fn.linkButton = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.linkButton.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $.data(this, "linkButton");
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "linkButton", {
                    options: $.extend({}, $.fn.linkButton.defaults, $.parser.parseOptions(this), option)
                });

            init(this);
        });
    };
    $.fn.linkButton.methods = {
        options: function (jq) {
            return $.data(jq[0], 'linkButton').options;
        }
    };
    $.fn.linkButton.defaults = {
        url: undefined, goal: undefined
    }
}(jQuery);
//panel
+function ($) {
    function init(target) {
        var opts = $(target).data('panel').options;
        var header = $(target).find('>.panel-heading');
        var body = $(target).find('>.panel-body');
        var footer = $(target).find('>.panel-footer');
        if (!body.length) {
            body = $("<div class='panel-body'/>").append($(target).contents());
            $(target).append(body);
            if (header.length) body.before(header);
            if (footer.length) body.after(footer);
        }
        if (!header.length) {
            header = $("<div class='panel-heading'/>");
            $('<div class="coodo-panel-header-title" ><i/>&nbsp;<span /></div>').appendTo(header);
            $('<div class="coodo-panel-header-tool"/>').appendTo(header);
            body.before(header);
        }
        if (!footer.length) {
            footer = $("<div class='panel-footer'/>");
            body.after(footer);
        }
        else {
            opts.footer = "";
        }

        $(target).addClass('panel panel-default coodo-panel');
        initAttr(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'panel').options;
        var tool = $(target).find('>.panel-heading>.coodo-panel-header-tool');//获取按钮栏
        var lastUserBtn = tool.find('>i.user-btn:last');

        if (opts.footer) {
            $(target).find('>.panel-footer').html(opts.footer);
        } else if (opts.footer == undefined) {
            $(target).find('>.panel-footer').remove();
        }
        if (opts.noheader) {
            $(target).find('>.panel-heading').remove();
        } else {
            //标题
            setTitle($(target), opts.title);
            if (opts.iconCls)
                $(target).find('>.panel-heading>.coodo-panel-header-title>i').addClass(opts.iconCls);
        }
        if (opts.tools) {
            if ($.isArray(opts.tools))
                $.each(opts.tools, function () {
                    var userBtn = $('<i class="user-btn" />').addClass(this.iconCls).click(this.handler);
                    if (lastUserBtn.length)
                        lastUserBtn.after(userBtn);
                    else
                        tool.prepend(userBtn);

                    lastUserBtn = userBtn;
                });
            else {
                if (lastUserBtn.length)
                    lastUserBtn.after($(opts.tools).children().addClass('user-btn'));
                else
                    tool.prepend($(opts.tools).children().addClass('user-btn'));
            }
        }
        if (opts.collapsible) {
            if (!tool.find('.btn-collapsible').length)
                $('<i class="glyphicon glyphicon-chevron-up btn-collapsible" />').click(function () {
                    if ($(this).hasClass('glyphicon-chevron-up'))
                        collapsible(target, this);
                    else
                        expand(target, this);
                }).appendTo(tool);
        } else {
            tool.children('.btn-collapsible').remove();
        }
        if (opts.minimizable) {
            if (!tool.find('.btn-mini').length)
                $('<i class="glyphicon glyphicon-minus btn-mini" />').click(function () {
                    close(target);
                }).appendTo(tool);
        } else {
            tool.children('.btn-mini').remove();
        }
        if (opts.maximizable) {
            if (!tool.find('.btn-max').length)
                $('<i class="glyphicon glyphicon-resize-full btn-max" state="normal" />').click(function () {
                    if ($(this).attr('state') == 'normal')
                        max(target);
                    else
                        restore(target);
                }).appendTo(tool);
        } else {
            tool.children('.btn-max').remove();
        }
        if (opts.closable) {
            if (!tool.find('.btn-close').length)
                $('<i class="glyphicon glyphicon-remove btn-close" />').click(function () {
                    close(target);
                }).appendTo(tool);
        } else {
            tool.children('.btn-close').remove();
        }
        if (opts.collapsed) {
            $(target).find('>.panel-tools,>.panel-body,>.panel-footer').hide();
        }
        if (opts.closed) {
            $(target).addClass('hidden');
        }

        setPanelSize(target, opts.width, opts.height);
    }

    function setPanelSize(target, width, height) {
        if (width) $(target).width(width);
        if (height)
            $(target).find('>.panel-body')
                .height(height)
                .css('overflow', 'auto');
        else
            $(target).find('>.panel-body').css('overflow', '');
    }

    function setTitle(target, title) {
        if (title)
            $(target).find('>.panel-heading>.coodo-panel-header-title>span').html(title);
    }

    function collapsible(target, btn) {
        var opts = $.data(target, 'panel').options;
        if (opts.onBeforeCollapse.call(target)) {
            opts.collapsed = true;
            if (!btn)
                btn = $(target).find('>.panel-heading>.coodo-panel-header-tool>.btn-collapsible');

            $(btn).removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down');

            if (opts.animate)
                $(target).find('.panel-tools,.panel-body,.panel-footer').slideUp(100);
            else
                $(target).find('.panel-tools,.panel-body,.panel-footer').hide();

            opts.onCollapse.call(target);
        }
    }

    function expand(target, btn) {
        var opts = $.data(target, 'panel').options;

        if (opts.onBeforeExpand.call(target)) {
            opts.collapsed = false;

            if (!btn)
                btn = $(target).find('>.panel-heading>.coodo-panel-header-tool>.btn-collapsible');

            $(btn).removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up');

            if (opts.animate)
                $(target).find('>.panel-tools,>.panel-body,>.panel-footer').slideDown(100);
            else
                $(target).find('>.panel-tools,>.panel-body,>.panel-footer').show();

            opts.onExpand.call(target);
        }
    }

    function max(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        opts.maximized = true;

        $(target).find('>.panel-heading>.coodo-panel-header-tool>.btn-max')
            .attr('state', 'max').removeClass('glyphicon-resize-full').addClass('glyphicon-resize-small');

        if (!state.original)
            state.original = {
                width: opts.width || $(target).width(),
                height: opts.height || $(target).find('>.panel-body').outerHeight()
            };

        var w = $(target).parent().width();
        if (w > $(window).width())
            w = $(window).width() * 0.9;

        var h = $(target).parent().height();
        if (h > $(window).height())
            h = $(window).height() * 0.9;
        //除去头、尾高度
        h = h - $(target).find('>.panel-heading').height() || 0 - $(target).find('>.panel-footer').height() || 0;

        if (opts.animate) {
            $(target).animate({width: w}, 100);
            $(target).find('>.panel-body').animate({height: h, overflow: 'auto'}, 100);
        } else {
            setPanelSize(target, w, h);
        }
        opts.onMaximize.call(target);
    }

    function restore(target) {
        var state = $.data(target, 'panel');
        var opts = state.options;
        opts.maximized = false;
        if (state.original) {
            $(target).find('>.panel-heading>.coodo-panel-header-tool>.btn-max')
                .attr('state', 'normal').removeClass('glyphicon-resize-small').addClass('glyphicon-resize-full');

            if (opts.animate) {
                $(target).animate({width: state.original.width}, 200);
                $(target).find('>.panel-body').animate({height: state.original.height}, 200);
            }
            else {
                setPanelSize(target, state.original.width, state.original.height);
            }

            opts.onRestore.call(target);
        }
    }

    function close(target) {
        var opts = $.data(target, 'panel').options;
        if (opts.animate)
            $(target).slideUp();
        else
            $(target).addClass('hidden');
        opts.onClose.call(target);
    }

    function open(target) {
        var opts = $.data(target, 'panel').options;
        if (opts.animate)
            $(target).slideDown();
        else
            $(target).removeClass('hidden');
        opts.onOpen.call(target);
    }

    $.fn.panel = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.panel.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('panel');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'panel', {
                    options: $.extend({}, $.fn.panel.defaults, $.parser.parseOptions(this), option, {title: $(this).attr('title')}),
                    original: null
                });

            $(this).removeAttr('title');
            init(this);
        });
    };
    $.fn.panel.methods = {
        options: function (jq) {
            return $.data(jq[0], 'panel').options;
        },
        reSize: function (jq, para) {
            return jq.each(function () {
                setPanelSize(this, para.width, para.height);
            });
        },
        open: function (jq) {
            return jq.each(function () {
                open(this);
            });
        },
        close: function (jq) {
            return jq.each(function () {
                close(this);
            });
        },
        collapse: function (jq) {
            return jq.each(function () {
                collapsible(this);
            });
        },
        expand: function (jq) {
            return jq.each(function () {
                expand(this);
            });
        },
        setTitle: function (jq, title) {
            return jq.each(function () {
                setTitle(this, title);
            });
        },
        maximize: function (jq) {
            return jq.each(function () {
                max(this)
            });
        },
        minimize: function (jq) {
            return jq.each(function () {
                close(this);
            });
        },
        restore: function (jq) {
            return jq.each(function () {
                restore(this)
            });
        },
        header: function (jq) {
            return jq.find('>.panel-heading');
        },
        body: function (jq) {
            return jq.find('>.panel-body');
        }
    };
    $.fn.panel.defaults = {
        title: '',
        footer: undefined,
        collapsible: false,
        collapsed: false,
        closable: false,
        closed: false,
        noheader: false,
        iconCls: undefined,
        width: undefined,
        height: undefined,
        minimizable: false,
        maximizable: false,
        maximized: false,
        animate: true,
        buttons: undefined,
        tools: undefined,
        onOpen: function () {
        },
        onClose: function () {
        },
        onBeforeCollapse: function () {
            return true;
        },
        onCollapse: function () {
        },
        onBeforeExpand: function () {
            return true;
        },
        onExpand: function () {
        },
        onMaximize: function () {
        },
        onRestore: function () {
        }
    };
}(jQuery);
//tabs
+function ($) {
    function init(target) {
        $(target).addClass('coodo-tabs');

        createView(target);
        initAttr(target);
        initEvent(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'tabs').options;
        var tabsDiv = $(target).find('>:not(.tab-content,.coodo-tabs-tag)');
        var tag = $(target).find('>.coodo-tabs-tag');

        if (tabsDiv.length) {
            tabsDiv.each(function (i) {
                var tabPanel = createPanel(target, {
                    title: $(this).attr('title'),
                    closable: $.parseBool($(this).attr('closable'))
                }, $(this));
                if (i == 0) {
                    tabPanel.addClass('active in');
                    tag.find('>.nav>li:eq(0)').addClass('active');
                }
            });
        }
        if (opts.tabsType) {
            tag.find('>.nav').removeClass('nav-tabs nav-pills').addClass('nav-' + opts.tabsType);
        }
        if (opts.scrolled) {
            if (!tag.find('>i').length) {
                var ul = tag.find('>.nav');
                var backward = $('<i class="glyphicon glyphicon-arrow-left pull-left tabs-scroll-left"></i>').insertBefore(ul);
                var forward = $('<i  class="glyphicon glyphicon-arrow-right pull-right tabs-scroll-right"></i>').insertBefore(ul);
                //关闭操作
                var groupBtn = $('<div class="btn-group pull-right"></div>').insertBefore(forward);
                var btn = $('<a href="javascript:void(0);" class="dropdown-toggle" data-toggle="dropdown">关闭操作<span class="caret"></span></a>').appendTo(groupBtn);
                var menu = $('<ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>')
                    .append('<li class="tabShowActive"><a href="javascript:void(0);">定位当前选项卡</a></li>')
                    .append('<li class="divider"></li>')
                    .append('<li class="tabCloseAll"><a  href="javascript:void(0);">关闭全部选项卡</a></li>')
                    .append('<li class="tabCloseOther"><a  href="javascript:void(0);">关闭其他选项卡</a></li>')
                    .appendTo(groupBtn);
                $(target).addClass('tabs-scroll');
            }
        } else {
            $(target).removeClass('tabs-scroll');
            tag.find('>i').remove();
            tag.find('>.btn-group').remove();
        }
        if (opts.fit) {
            $(target).addClass('coodo-tabs-fit');
            setHeight(target);
            $(window).resize(function () {
                setHeight(target);
            });
        } else {
            $(target).removeClass('coodo-tabs-fit');
            if (opts.height) $(target).find('>.tab-content').height(opts.height);
            if (opts.width) $(target).width(opts.width);
        }
    }

    function setHeight(target) {
        var h = $(target).parent().height();
        var _parent = $(target).parent();
        if (_parent.is('body')) {
            h = $(window).height()
                - (+$('body').css('padding-top').replace('px', ''))
                - (+$('body').css('padding-bottom').replace('px', ''))
                - (+$('body').css('border-top-width').replace('px', '') || 0)
                - (+$('body').css('border-bottom-width').replace('px', '') || 0);
        }
        h -= $(target).find('ul.nav').height();
        $(target).find('>.tab-content').height(h);
    }

    function initEvent(target) {
        var opts = $.data(target, 'tabs').options;
        var tag = $(target).find('>.coodo-tabs-tag');
        var tagUl = tag.find('>.nav');

        $(target).find('a[data-toggle="tab"]').off('.tab').on('shown.bs.tab', function (e) {
            var tabPanel = getTab(target, e.target.text);
            opts.onSelect.call(getTab(target, e.target.text)[0], tabPanel.attr('id'));
        });

        $(target).off('.tabs')
            .on('click.tabs', '>.coodo-tabs-tag>.nav>li>.close', function () {
                var index = $(this).parent().index();
                removeTab(target, index);
            })
            .on('click.tabs', '>.coodo-tabs-tag>i', function () {
                var pos = 0;
                if ($(this).hasClass('tabs-scroll-left')) {
                    pos = tagUl.scrollLeft() - tagUl.width();
                } else {
                    pos = tagUl.scrollLeft() + tagUl.width();
                }
                tagUl.animate({scrollLeft: pos}, 400);
            })
            .on('click.tabs', '>.coodo-tabs-tag>.btn-group .tabShowActive', function () {
                var currTab = tagUl.children('.active');
                var preTabsW = getContentWidth(currTab.prevAll());
                var ulW = $("#tab2>.nav").outerWidth();
                var pos = Math.floor(preTabsW / ulW) * ulW;

                tagUl.animate({scrollLeft: pos}, 400);

                function getContentWidth(tabs) {
                    var k = 0;
                    $(tabs).each(function () {
                        k += $(this).outerWidth(true);
                    });
                    return k;
                }
            })
            .on('click.tabs', '>.coodo-tabs-tag>.btn-group .tabCloseAll', function () {
                $(target).find('>.coodo-tabs-container').children().each(function () {
                    var title = $(this).attr('id');
                    if (tagUl.find('>li>a[href="#' + title + '"]').prev('.close').length) {
                        removeTab(target, title);
                    }
                });
            })
            .on('click.tabs', '>.coodo-tabs-tag>.btn-group .tabCloseOther', function () {
                $(target).find('>.coodo-tabs-container').children().not(".active").each(function () {
                    var title = $(this).attr('id');
                    if (tagUl.find('>li>a[href="#' + title + '"]').parent().find('>.close').length) {
                        removeTab(target, title);
                    }
                });
            });
    }

    function createView(target) {
        //var opts = $(target).data('tabs').options;

        var tag = $(target).find('>.coodo-tabs-tag');
        if (!tag.length) {
            tag = $('<div class="coodo-tabs-tag"><ul class="nav" /></div>').appendTo(target);
        }

        var container = $(target).find('>.coodo-tabs-container');
        if (!container.length)
            container = $('<div class="tab-content coodo-tabs-container" />').appendTo(target);
    }

    function createPanel(target, options, panel) {
        var opts = $.data(target, 'tabs').options;
        var option = $.extend({}, $.fn.tabs.panelDefaults, options);
        var ul = $(target).find('>.coodo-tabs-tag>ul');
        var container = $(target).find('>.coodo-tabs-container');

        if (option.title && !exists(target, option.title)) {
            var li = $('<li />').append($('<a data-toggle="tab" />')
                .text(option.title)
                .attr({'href': '#' + option.title}))
                .appendTo(ul);

            if (option.closable) {
                $('<i class="close">&times;</i>').insertBefore(li.find('a'));
            }
            panel.removeAttr('title')
                .addClass('tab-pane')
                .attr({id: option.title, role: 'tabpanel'})
                .appendTo(container);

            if (opts.fade) panel.addClass("fade");
            return panel;
        }
    }

    function exists(target, title) {
        var _panel = getTab(target, title);
        return _panel.length > 0;
    }

    function addTab(target, param) {
        var opts = $.data(target, 'tabs').options;

        var panel;
        if (opts.singlePages)
            panel = $('<div/>').append(param.content);
        else
            panel = $('<iframe frameborder="0" src="' + param.content + '"></iframe>');
        var tabPanel = createPanel(target, param, panel);
        if ($(target).find('>.nav>li').length == 1)
            selectTab(target);

        if (tabPanel)
            opts.onAdd.call(tabPanel[0]);
    }

    function removeTab(target, temp) {
        var opts = $.data(target, 'tabs').options;
        var tabPanel, activeId;

        if (!isNaN(temp)) {
            $(target).find('>.coodo-tabs-tag>.nav>li').eq(temp).remove();
            tabPanel = $(target).find('>div.coodo-tabs-container>.tab-pane').eq(temp);
        } else {
            $(target).find('>.coodo-tabs-tag>.nav>li>a[href="#' + temp + '"]').parent().remove();
            tabPanel = $(target).find('>div.coodo-tabs-container>.tab-pane[id="' + temp + '"]');
        }
        if (tabPanel.hasClass('active')) {
            //获取下一下元素
            if (tabPanel.next().length)
                activeId = tabPanel.next().attr('id');
            else
                activeId = tabPanel.prev().attr('id');
        }
        tabPanel.remove();
        if (activeId) selectTab(target, activeId);
        opts.onRemove.call(tabPanel[0]);
    }

    function getTab(target, temp) {
        if (!isNaN(temp))
            return $(target).find('>div.coodo-tabs-container>.tab-pane').eq(temp);
        else
            return $(target).find('>div.coodo-tabs-container>.tab-pane[id="' + temp + '"]');
    }

    function selectTab(target, index) {
        var opts = $.data(target, 'tabs').options;
        var temp = index == null || index == undefined ? 0 : index;
        if ($.isNumeric(temp)) {
            $(target).find('>.coodo-tabs-tag>.nav>li:eq(' + temp + ')>a').tab('show');//.trigger('click');
        } else {
            $(target).find('>.coodo-tabs-tag>.nav>li>a[href=' + '#' + temp + ']').tab('show');//.trigger('click');
        }
    }

    $.fn.tabs = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.tabs.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('tabs');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'tabs', {
                    options: $.extend({}, $.fn.tabs.defaults, $.parser.parseOptions(this), option)
                });
            init(this);
        });
    };
    $.fn.tabs.methods = {
        options: function (jq) {
            return $.data(jq[0], 'tabs').options;
        },
        tabs: function (jq) {
            return jq.eq(0).find('>div.coodo-tabs-container>div');
        },
        add: function (jq, param) {
            return jq.each(function () {
                addTab(this, param);
            });
        },
        remove: function (jq, temp) {
            return jq.each(function () {
                removeTab(this, temp);
            });
        },
        getTab: function (jq, temp) {
            return getTab(jq.eq(0), temp)[0];
        },
        getSelected: function (jq) {
            return jq.eq(0).find('>div.coodo-tabs-container>div.active')[0];
        },
        select: function (jq, temp) {
            return jq.each(function () {
                selectTab(this, temp);
            });
        },
        exists: function (jq, title) {
            return exists(jq[0], title);
        }
    };
    $.fn.tabs.defaults = {
        tabsType: 'tabs', // tabs,pills
        height: undefined,
        width: undefined,
        fade: true,
        fit: false,
        singlePages: true,
        scrolled: false,
        onSelect: function (title) {
        },
        onAdd: function () {
        },
        onRemove: function () {
        }
    };
    $.fn.tabs.panelDefaults = {
        title: '', content: undefined, closable: false
    };
}(jQuery);
//accordion
+function ($) {
    function init(target) {
        $(target).addClass('coodo-accordion');
        var opts = $.data(target, 'accordion').options;
        var accDiv = $(target).find('>div');
        accDiv.each(function (index) {
            createPanel(target, this);
        });

        initAttr(target);
        initEvent(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'accordion').options;

        if (opts.width) {
            $(target).width(opts.width);
        }
        if ($.isNumeric(opts.selected)) {
            $(target).children(':eq(' + opts.selected + ')').panel('expand');
        }
    }

    function initEvent(target) {
        var opts = $(target).data('accordion').options;

        $(target).off('.accordion')
            .on('click.accordion', '>.coodo-panel>.panel-heading', function () {
                var _panel = $(this).parent();
                if (_panel.hasClass('expand'))
                    _panel.panel('collapse');
                else {
                    _panel.panel('expand');
                    opts.onSelect.call(_panel, _panel.panel('options').title);
                }
            });
    }

    function createPanel(target, panelDiv, option) {
        var opts = $.data(target, 'accordion').options;
        var _panel = $(panelDiv);
        _panel.panel($.extend({}, {
            title: $(panelDiv).attr('title'),
            collapsed: true,
            animate: opts.animate
        }, option || {}, {
            onBeforeExpand: function () {
                if (!opts.multiple) {
                    $(this).siblings('.expand').each(function () {
                        $(this).removeClass('expand').panel('collapse');
                    });
                }
                return true;
            },
            onExpand: function () {
                $(this).addClass('expand');
            },
            onCollapse: function () {
                $(this).removeClass('expand');
            }
        }));

        return _panel;
    }

    function add(target, option) {
        var opts = $.data(target, 'accordion').options;
        createPanel(target, '<div />', option).appendTo(target);
        opts.onAdd.call(target, option.title);
    }

    function remove(target, title) {
        var opts = $.data(target, 'accordion').options;
        var result = true;
        if (opts.onBeforeRemove)
            result = opts.onBeforeRemove.call(target, title);

        if (result) {
            getPanel($(target), title).remove();
            opts.onRemove.call(target, title);
        }
    }

    function getPanel(target, title) {
        return target.find('>.coodo-panel:has(.coodo-panel-header-title>span:contains("' + title + '"))');
    }

    $.fn.accordion = function (options, param) {
        if (typeof options == 'string') {
            return $.fn.accordion.methods[options](this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('accordion');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'accordion', {
                    options: $.extend({}, $.fn.accordion.defaults, $.parser.parseOptions(this), option)
                });

            init(this);
        });
    };
    $.fn.accordion.methods = {
        options: function (jq) {
            return $.data(jq[0], 'accordion').options;
        },
        panels: function (jq) {
            return jq.find('>.coodo-panel');
        },
        getPanel: function (jq, title) {
            return getPanel(jq, title);
        },
        select: function (jq, title) {
            return jq.each(function(){
                getPanel(this, title).panel('expand');
            });
        },
        getSelected: function (jq) {
            return jq.find('>.coodo-panel.expand');
        },
        add: function (jq, option) {
            return jq.each(function () {
                add(this, option);
            });
        },
        remove: function (jq, title) {
            return jq.each(function () {
                remove(this, title);
            });
        }
    };
    $.fn.accordion.defaults = {
        width: undefined, animate: true, selected: 0, multiple: false,
        onSelect: function (title) {
        },
        onAdd: function (title) {
        },
        onBeforeRemove: undefined,
        onRemove: function (title) {
        }
    };
}(jQuery);
//grid
+function ($) {

    function init(target) {
        var opts = $.data(target, 'grid').options;
        var para = {}, grid, gridBody;

        if (!opts.title)
            para['noheader'] = true;

        grid = $(target).parents('.coodo-grid-panel:eq(0)');
        if (!grid.length) {
            grid = $('<div class="coodo-grid-panel" />');
            if (para['noheader']) grid.addClass('coodo-grid-panel-noBorder');
            para['height'] = "";
            grid = grid.panel($.extend({}, opts, para)).insertBefore(target);
        }
        gridBody = grid.panel('body');
        if (!$(target).parents('.panel-body:eq(0)').is(gridBody)) gridBody.append($('<div class="fixed-table-body"/>').append(target));
        $(target).addClass("table coodo-grid");

        initAttr(target);
        initEvent(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'grid').options;
        var pageTool,
            toolbarH = 0,
            pageH = 0,
            tableBody = $(target).parent();

        if (opts.striped) {
            $(target).addClass('table-striped');
        } else {
            $(target).removeClass('table-striped');
        }
        if (opts.bordered) {
            $(target).addClass('table-bordered');
        } else {
            $(target).removeClass('table-bordered');
        }
        if (opts.hover) {
            $(target).addClass('table-hover');
        } else {
            $(target).removeClass('table-hover');
        }
        if (opts.condensed) {
            $(target).addClass('table-condensed');
        } else {
            $(target).removeClass('table-condensed');
        }
        if (opts.pagination) {
            if (!tableBody.next('.coodo-pagination').length) {
                pageTool = $('<div />').pagination({
                    pageSize: opts.pageSize,
                    showPage: opts.showPage,
                    displayMsg: opts.displayMsg,
                    onSelectPage: function (number) {
                        loadRemoteData(target, {pageNumber: number});
                    }
                });
                if (opts.condensed) pageTool.addClass('pagination-condensed'); else pageTool.removeClass('pagination-condensed');
                tableBody.after(pageTool);
                pageH = pageTool.outerHeight() + (+pageTool.css('border-left-width').replace('px', '') || 0);
            }
        } else {
            tableBody.next('.coodo-pagination').remove();
        }
        if (opts.columns && opts.columns.length) {
            if ($.isArray(opts.columns[0])) {
                var columns = [];
                $.each(opts.columns, function () {
                    columns.push([].concat(this));
                });
                opts.dataColumns = buildDataColumn(columns, 0, opts.columns[0].length);
                createHeader2(target);
            }
            else
                createHeader(target);
        }
        if (opts.data) {
            var obj = {};
            if ($.isArray(opts.data)) {
                obj.total = opts.data.length;
                obj.rows = opts.data;
            } else {
                obj = opts.data;
            }
            loadData(target, obj, function (target, total) {
                if (pageTool) pageTool.pagination('build', total);
            });

        } else if (opts.url && typeof opts.url == "string") {
            loadRemoteData(target, null, function (target, total) {
                if (pageTool)
                    pageTool.pagination('build', total);
            });
        }
        if (opts.toolbar || opts.columnChoose) {
            var toolbar = tableBody.siblings('.coodo-grid-toolbar');
            if (!toolbar.length) {
                toolbar = $('<div class="coodo-grid-toolbar"><div class="customToolbar" /><div class="sysToolbar" /></div>');
                tableBody.prev('.table-header').before(toolbar);
            }
            if (opts.toolbar) {
                var customTool = toolbar.children('.customToolbar');
                if ($.isArray(opts.toolbar))
                    $.each(opts.toolbar, function () {
                        $('<i />').addClass(this.iconCls).click(this.handler).appendTo(customTool);
                    });
                else
                    $(opts.toolbar).children().appendTo(customTool);
            }
            if (opts.columnChoose) {
                if (!toolbar.find('.sysToolbar>.columnChoose').length)
                    toolbar.children('.sysToolbar').append(createColumnChoose(target));
            }
            else
                toolbar.find('.sysToolbar>.columnChoose').remove();

            toolbarH = toolbar.outerHeight();
        }

        if (opts.height) {
            var tableHeader = tableBody.parent().find('>.table-header');
            var headerH = tableHeader.outerHeight();
            var _h = opts.height - toolbarH - headerH - pageH;
            tableBody.css({'max-height': _h, 'overflow-y': 'auto'});
        }
    }

    function initEvent(target) {
        var state = $.data(target, 'grid');
        var opts = state.options;

        $(target).off('.grid')
            .on('click.grid', '.coodo-grid-data-row>.coodo-grid-data-cell:not(.coodo-grid-checkBox)', function () {
                var row = $(this).parent();
                opts.onClickCell.call(this, +row.attr('coodo-grid-rowindex'), $(this).attr('field'), $(this).find('>.coodo-grid-data').html());
            }) //click cell
            .on('dblclick.grid', '.coodo-grid-data-row>.coodo-grid-data-cell:not(.coodo-grid-checkBox)', function () {
                var row = $(this).parent();
                opts.onDblClickCell.call(this, +row.attr('coodo-grid-rowindex'), $(this).attr('field'), $(this).find('>.coodo-grid-data').html());
            })   //dblClick cell
            .on('click.grid', '.coodo-grid-data-row', function () {
                if (!opts.disableSelect) selectRow(target, $(this));
            }) //click row
            .on('dblclick.grid', '.coodo-grid-data-row', function () {
                var rowIndex = +$(this).attr('coodo-grid-rowindex');
                opts.onDblClickRow.call(this, rowIndex, state.data.rows[rowIndex]);
            }) //dblClick row
            .on('click.grid', '.coodo-grid-data-row>.coodo-grid-checkBox>:checkbox', function (e) {
                e.stopPropagation();
            }) //click dataRow checkbox
            .on('change.grid', '.coodo-grid-data-row>.coodo-grid-checkBox>:checkbox', function () {
                var row = $(this).parents('.coodo-grid-data-row');
                if (this.checked)
                    checkRow(target, row);
                else
                    uncheckRow(target, row);
            }) //dataRow checkbox onchange
            .on('keydown.grid', '.coodo-grid-data-row>.cell-editing>.cell-editor>input[type="number"]', function (e) {
                var otherKey = [8, 46, 37, 39];
                if (e.key.replace(/\d|\.|e/, '') && otherKey.indexOf(e.keyCode) == -1) return false;
            }) //number editor
            .on('input propertychange.grid', '.coodo-grid-data-row>.cell-editing>.cell-editor>input[type="number"]', function () {
                var v = $(this).val();
                var temp = v.match(/[^\d\.]/g);
                if (temp) {
                    var realPos = e.target.selectionStart - temp.length;
                    $(this).val(v.replace(/[^\d\.]/g, ''));
                    e.target.selectionStart = e.target.selectionEnd = realPos;
                }
            }); //number editor

        $(target).parent().prev('.table-header').off('.grid')
            .on('change.grid', '.coodo-grid-header-row .coodo-grid-selectAll', function () {
                //列头的复选框实现全选功能
                if (this.checked) {
                    $(target).find('input:checkbox').prop('checked', true);
                    if (opts.checkOnSelect)
                        $(target).find('.coodo-grid-data-row:not(.coodo-grid-data-row-selected)').each(function () {
                            selectRow(target, $(this));
                        });
                } else {
                    $(target).find('input:checkbox').prop('checked', false);
                    if (opts.checkOnSelect)
                        $(target).find('.coodo-grid-data-row').each(function () {
                            unselectRow(target, $(this));
                        });
                }
                opts.onCheckAll.call(this, this.checked);
            }) //checkboxAll onchange
            .on('click.grid', '.coodo-grid-header-row>td[coodo-grid-sort]', function () {
                //清除掉其他排序条件，通过标头一次只能有一个排序依据
                var rows = $(target).find('.coodo-grid-header-row');
                rows.find('>td[coodo-grid-sort]').not(this).attr('coodo-grid-sort', '');
                rows.find('>td .caret').removeClass('caret');
                var order = "asc";
                var sortFlag = $(this).find('.btn-group');

                switch ($(this).attr('coodo-grid-sort')) {
                    case "":
                    case "desc":
                        sortFlag.addClass('dropup');
                        break;
                    case "asc":
                        sortFlag.removeClass('dropup');
                        order = "desc";
                        break;
                }

                sortFlag.find('span').addClass('caret');
                opts.sortName = $(this).attr('field');
                $(this).attr('coodo-grid-sort', order);
                opts.sortOrder = order;

                loadRemoteData(target);

                opts.onSortColumn.call(target, opts.sortName, order);
            }); //sort
    }

    //生成列头
    function createHeader(target) {
        var opts = $.data(target, 'grid').options;

        var tableBody = $(target).parent();
        var _header = tableBody.prev('.table-header');
        if (!_header.length) _header = $(target).clone().removeAttr('id').addClass('table-header').insertBefore(tableBody);
        _header.children().remove();
        var row = $('<tr class="coodo-grid-header-row"/>').appendTo(_header);
        if (opts.rowNumbers) {
            var rowNumber = $('<td class="coodo-grid-rowNumber"/>').appendTo(row);
        }
        for (var i = 0; i < opts.columns.length; i++) {
            var col = $.extend({}, $.fn.grid.columnDefaults, opts.columns[i]);

            if (!col.checkbox && col.title == undefined) continue;

            var column = $('<td />').attr('field', col.field);
            if (col.checkbox) {
                column.addClass('coodo-grid-checkBox');
                if (!opts.singleSelect)
                    column.append('<input class="coodo-grid-selectAll" type="checkbox" />');
            }
            else
                $('<div class="coodo-grid-header" />').attr('title', col.title).text(col.title).appendTo(column);
            if (col.sortable) {
                column.attr('coodo-grid-sort', "");
                column.find('>div').append($('<div class="btn-group dropup"><span>&nbsp;</span></div>'));
            }
            if (col.halign || col.align) column.addClass('text-' + (col.halign || col.align));
            if (col.width) column.width(col.width);
            if (col.hidden) column.addClass('hidden');

            row.append(column);
        }
    }

    //支持多列头呈现
    function createHeader2(target) {
        var opts = $.data(target, 'grid').options;

        var tableBody = $(target).parent();
        var _header = tableBody.prev('.table-header');
        if (!_header.length) _header = $(target).clone().removeAttr('id').addClass('table-header').insertBefore(tableBody);

        _header.children().remove();

        $.each(opts.columns, function (i) {
            var row = $('<tr class="coodo-grid-header-row" />');
            //行号
            if (i == 0 && opts.rowNumbers) {
                var rowNum = $('<td class="coodo-grid-rowNumber" />').attr('rowSpan', opts.columns.length).appendTo(row);
                if (opts.columnChoose) createColumnChoose(target, rowNum, opts.dataColumns);
            }

            for (var j = 0; j < this.length; j++) {
                var col = $.extend({}, $.fn.grid.columnDefaults, this[j]);

                if (!col.checkbox && col.title == undefined) continue;

                var column = $('<td/>').attr('field', col.field);
                if (col.checkbox) {
                    column.addClass('coodo-grid-checkBox');
                    if (!opts.singleSelect)
                        column.append('<input class="coodo-grid-selectAll" type="checkbox" />');
                }
                else
                    $('<div class="coodo-grid-header" />').attr('title', col.title).text(col.title).appendTo(column);

                if (col.sortable) {
                    column.attr('coodo-grid-sort', "");
                    column.find('>div').append($('<div class="btn-group dropup"><span>&nbsp;</span></div>'));
                }
                if (col.halign || col.align) column.addClass('text-' + (col.halign || col.align));
                if (col.width) column.width(col.width);
                if (col.rowSpan) column.attr('rowSpan', col.rowSpan);
                if (col.colSpan) column.attr('colSpan', col.colSpan);
                if (col.hidden) column.addClass('hidden');

                row.append(column);
            }

            _header.append(row);
        });
    }

    function loadRemoteData(target, param, fnc) {
        var state = $.data(target, 'grid');
        var opts = state.options;

        if (param) $.extend(opts, param);

        var searchParam = {};

        //检查是否分页
        if (opts.pagination)
            $.extend(searchParam, {
                begin: (opts.pageNumber - 1) * opts.pageSize + 1,
                end: (opts.pageNumber - 1) * opts.pageSize + opts.pageSize
            });
        else
            $.extend(searchParam, {begin: 0, end: Number.MAX_VALUE});

        $.extend(searchParam, {pageNumber: opts.pageNumber, pageSize: opts.pageSize});

        if (opts.queryParams)
            $.extend(searchParam, opts.queryParams);
        if (opts.sortName) {
            $.extend(searchParam, {sort: opts.sortName});
            if (opts.sortOrder)
                $.extend(searchParam, {order: opts.sortOrder});
            else
                $.extend(searchParam, {order: 'asc'});
        }

        $.extend(searchParam, {timeFlag: new Date().toString()});

        //数据
        if (opts.url) {
            var gridContainer = $(target).parents('.panel-body:eq(0)');
            $.ajax({
                url: opts.url,
                data: searchParam,
                type: opts.method,
                dataType: "json",
                beforeSend: function () {
                    gridContainer.openMask({msg: opts.loadMsg});
                },
                success: function (data) {
                    loadData(target, data, fnc);
                },
                complete: function () {
                    gridContainer.closeMask();
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    gridContainer.closeMask();
                    opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
                }
            });
        }
    }

    function loadData(target, data, fnc) {
        var state = $.data(target, 'grid'), gridPanelBody = $(target).parents('.panel-body:eq(0)');
        if (!state) return; //dom数据已丢失，停止加载
        var opts = state.options;
        state.selectRows.splice(0);

        //清除旧数据
        $(target).find("tr.coodo-grid-data-row").remove();
        //清除全选按钮的选中状态
        gridPanelBody.find('.table-header>tr.coodo-grid-header-row .coodo-grid-selectAll').prop('checked', false);

        if (data && data.rows && data.rows.length) {
            gridPanelBody.find('.noRecord').remove();
            gridPanelBody.find('.coodo-pagination').removeClass('hidden');

            state.data = data;
            $.each(data.rows, function (j) {
                var rowData;
                if ($.isArray(opts.columns[0]))
                    rowData = createRowData2(target, this, j);
                else
                    rowData = createRowData(target, this, j);

                $(target).append(rowData);
            });

            //实现单元格合并
            $.each($.grep(opts.columns, function (o) {
                if (o && o['merge'])
                    return o;
            }), function () {
                var columns = $(target).find('td.coodo-grid-data-cell[field="' + this.field + '"]');
                if (columns)
                    for (var i = 0; i < columns.length; i++) {
                        var cEle = columns[i];
                        var k = 0;
                        if ($(cEle).is(":hidden"))
                            continue;
                        for (var j = i + 1; j < columns.length; j++) {
                            var nEle = columns[j];
                            if ($(cEle).text() == $(nEle).text()) {
                                k++;
                                $(nEle).hide();
                            }
                            else
                                break;
                        }
                        if (k > 0)
                            $(cEle).attr('rowspan', k + 1).css('vertical-align', 'middle');
                    }
            });
        }
        else {
            state.data = {total: 0, rows: []};
            gridPanelBody.find('.coodo-pagination').addClass('hidden');
            if (!gridPanelBody.find('.noRecord').length)
                $(target).parent().after('<div class="noRecord">' + opts.noRecordMsg + '</div>');
        }

        if (fnc)
            fnc(target, state.data.total);

        initIndent(target);
        opts.onLoadSuccess.call(target, data);
    }

    function initIndent(target) {
        var tableBody = $(target).parent();
        var tableHeader = tableBody.prev('.table-header');
        var tr = tableHeader.find('>tbody>tr');
        var headerIndent = tr.eq(0).find('>td.indent');
        var indentWidth = tableBody[0].offsetWidth - tableBody[0].scrollWidth;
        if (indentWidth) {
            if (!headerIndent.length) {
                var trLen = tr.length;
                headerIndent = $('<td class="indent"></td>').width(indentWidth);
                if (trLen > 1)  headerIndent.attr('rowspan', trLen);
                tr.eq(0).append(headerIndent);
            }
        } else {
            headerIndent.remove();
        }
    }

    //生成一行数据，row行数据
    function createRowData(target, row, rowIndex) {
        var opts = $.data(target, 'grid').options;
        //行号
        var rowNum = (opts.pageNumber - 1) * opts.pageSize + rowIndex;
        var rowData = $('<tr class="coodo-grid-data-row" />').attr('coodo-grid-rowIndex', rowIndex);
        var rowStyle = opts.rowStyle(rowIndex, row);
        if (rowStyle) rowData.attr('style', rowStyle);

        //行号
        if (opts.rowNumbers)
            rowData.append($('<td class="coodo-grid-rowNumber" />').text(rowNum + 1));

        for (var i = 0; i < opts.columns.length; i++) {
            var col = $.extend({}, $.fn.grid.columnDefaults, opts.columns[i]);

            if (!col.checkbox && col.title == undefined) continue;

            var column = $('<td class="coodo-grid-data-cell" />').attr('field', col.field).appendTo(rowData);
            var dataContent = row[opts.columns[i].field];

            if (col.align) {
                column.addClass('text-' + col.align);
            }
            if (col.hidden) {
                column.addClass('hidden');
            }
            if (col.width) {
                column.width(col.width);
            }
            if (col.editor) {
                column.attr('editor', col.editor.type || col.editor);
            }
            if (col.checkbox) {
                column.addClass('coodo-grid-checkBox text-center').append('<input type="checkbox" />');
            } else {
                var dataDiv = $('<div class="coodo-grid-data" />').appendTo(column);
                if (col.formatter)
                    dataDiv.append(col.formatter.call(dataDiv, dataContent, row, rowIndex));
                else
                    dataDiv.attr('title', dataContent).append(dataContent);
            }
            if (col.styler) {
                var rStyle = col.styler.call(column, dataContent, row, rowIndex);
                if (rStyle && typeof rStyle == "object") column.css(rStyle);
            }
        }

        return rowData;
    }

    //支持多列头呈现
    function createRowData2(target, row, rowIndex) {
        var opts = $.data(target, 'grid').options;
        //行号
        var rowNum = (opts.pageNumber - 1) * opts.pageSize + rowIndex;

        var rowData = $('<tr class="coodo-grid-data-row" />').attr('coodo-grid-rowIndex', rowIndex);
        var rowStyle = opts.rowStyle(rowIndex, row);
        if (rowStyle) rowData.attr('style', rowStyle);

        //行号
        if (opts.rowNumbers)
            rowData.append($('<td class="coodo-grid-rowNumber" />').text(rowNum + 1));

        $.each(opts.dataColumns, function () {
            var col = $.extend({}, $.fn.grid.columnDefaults, this);
            if (col.title != undefined || col.checkbox) {
                var column = $('<td class="coodo-grid-data-cell" />').attr('field', col.field).appendTo(rowData);
                var dataContent = row[col.field];

                if (col.align) {
                    column.addClass('text-' + col.align);
                }
                if (col.hidden) {
                    column.addClass('hidden');
                }
                if (col.width) {
                    column.width(col.width);
                }
                if (col.editor) {
                    column.attr('editor', col.editor.type || col.editor);
                }
                if (col.checkbox) {
                    column.addClass('coodo-grid-checkBox text-center').append('<input type="checkbox" />');
                } else {
                    var dataDiv = $('<div class="coodo-grid-data" />').appendTo(column);
                    if (col.formatter)
                        dataDiv.append(col.formatter.call(dataDiv, dataContent, row, rowIndex));
                    else
                        dataDiv.attr('title', dataContent).append(dataContent);
                }
                if (col.styler) {
                    var rStyle = col.styler.call(column, dataContent, row, rowIndex);
                    if (rStyle && typeof rStyle == "object") column.css(rStyle);
                }
            }
        });
        return rowData;
    }

    //构建实际要显示的数据列
    function buildDataColumn(columns, index, count) {
        var result = [];
        for (var i = 0; i < count; i++) {
            var col = columns[index][i];
            if (!col) break;
            if (col.field || col.checkbox)
                result.push(col);
            else if (col.colSpan) {
                $.each(buildDataColumn(columns, index + 1, col.colSpan), function () {
                    result.push(this);
                });
                if (index > 0)
                    count -= col.colSpan - 1;
            }
        }

        columns[index].splice(0, count);

        return result;
    }

    //选中或取消选中数据行,id可以索引，也可以是idField值；selected选中状态，true为选中，false为取消选中
    function selectOrUnSelectRecord(target, id, selected) {
        var state = $.data(target, 'grid');
        var data = state.data;
        var row;
        var rowIndex = null;

        if (!data.rows.length)
            return;

        if (typeof id == 'number') {
            rowIndex = +id;
        }
        else if (state.options.idField) {
            $.grep(data.rows, function (ele, i) {
                if (ele[state.options.idField] == id)
                    rowIndex = i;
            });
        }

        if (rowIndex != undefined && rowIndex != null && rowIndex < data.rows.length) {
            row = $(target).find('tr[coodo-grid-rowIndex=' + rowIndex + ']');

            if (selected)
                selectRow(target, row);
            else
                unselectRow(target, row);
        }
    }

    function selectRow(target, row) {
        var state = $.data(target, 'grid');
        var opts = $.data(target, 'grid').options;

        var selectRowIndex = +row.attr('coodo-grid-rowindex');
        var selectRowData = state.data.rows[selectRowIndex];

        if (opts.singleSelect) {
            //单选
            var currentRow = $(target).find('tr.coodo-grid-data-row-selected');
            if (currentRow[0] != row[0]) {
                unselectRow(target, currentRow);
            }
        } else {
            //多选
            if ($.inArray(selectRowData, state.selectRows) > -1) {
                unselectRow(target, row);
                return;
            }
        }

        opts.onClickRow.call(this, selectRowIndex, state.data.rows[selectRowIndex]);

        if (!row.hasClass('coodo-grid-data-row-selected')) {

            state.selectRows.push(selectRowData);

            row.addClass('coodo-grid-data-row-selected');

            //使复选框选中
            if (opts.selectOnCheck) {
                row.find('.coodo-grid-checkBox>:checkbox').each(function () {
                    this.checked = true;
                });
                updateAllSelectState(target);
            }

            //触发选中事件
            opts.onSelect.call(row[0], selectRowIndex, selectRowData);
        }
    }

    function unselectRow(target, row) {
        var state = $.data(target, 'grid');
        var opts = $.data(target, 'grid').options;

        if (row.hasClass('coodo-grid-data-row-selected')) {
            var currentRowIndex = +row.attr('coodo-grid-rowindex');
            var currentRowData = state.data.rows[currentRowIndex];
            var _index = $.inArray(currentRowData, state.selectRows);
            if (_index >= 0) state.selectRows.splice(_index, 1);

            row.removeClass('coodo-grid-data-row-selected');
            if (opts.selectOnCheck) {
                row.find('.coodo-grid-checkBox>:checkbox').each(function () {
                    this.checked = false;
                });
                updateAllSelectState(target);
            }

            //触发取消选中事件
            opts.onUnselect.call(row[0], currentRowIndex, currentRowData);
        }
    }

    function checkOrunCheckRow(target, idValue, checked) {
        var state = $.data(target, 'grid');
        var rowIndex = -1;

        if (typeof idValue == 'number')
            rowIndex = idValue;
        else if (state.options.idField)
            rowIndex = getRowIndex(target, idValue);

        if (rowIndex >= 0) {
            var row = $(target).find('tr[coodo-grid-rowIndex=' + rowIndex + ']');

            if (checked)
                checkRow(target, row);
            else
                uncheckRow(target, row);
        }
    }

    function checkRow(target, row) {
        var state = $.data(target, 'grid');
        var opts = state.options;
        var checkbox = row.find('>.coodo-grid-checkBox>:checkbox');
        if (checkbox.length) {
            checkbox.prop('checked', true);
            if (opts.checkOnSelect)
                selectRow(target, row);

            updateAllSelectState(target);
            var rowIndex = +row.attr('coodo-grid-rowindex');
            opts.onCheck.call(this, rowIndex, state.data.rows[rowIndex], true);
        }
    }

    function uncheckRow(target, row) {
        var state = $.data(target, 'grid');
        var opts = state.options;
        var checkbox = row.find('>.coodo-grid-checkBox>:checkbox');
        if (checkbox.length) {
            checkbox.prop('checked', false);
            if (opts.checkOnSelect)
                unselectRow(target, row);

            updateAllSelectState(target);
            var rowIndex = +row.attr('coodo-grid-rowindex');
            opts.onCheck.call(this, rowIndex, state.data.rows[rowIndex], false);
        }
    }

    function updateAllSelectState(target) {
        var opts = $.data(target, 'grid').options;

        if (!opts.singleSelect) {
            var cbxCollection = $(target).find('tr>.coodo-grid-checkBox>:checkbox:not(:checked)');
            if (cbxCollection.length)
                $(target).parent().prev('.table-header').find('tr:eq(0)>td>:checkbox').prop("checked", false);
            else
                $(target).parent().prev('.table-header').find('tr:eq(0)>td>:checkbox').prop("checked", true);
        }
    }

    function appendRow(target, row) {
        var gridData = $.data(target, 'grid').data;
        var rowIndex = +$(target).find('tr:last').attr('coodo-grid-rowIndex');
        var rowResult = createRowData(target, row, rowIndex + 1 || 0);

        $(target).append(rowResult);

        gridData.rows.push(row);
        gridData.total++;

        $(target).parent().find('.noRecord').remove();

        initIndent(target);
    }

    function insertRow(target, index, row) {
        var gridData = $.data(target, 'grid').data;
        var rowResult = null, trColls = null;

        if ($.isNumeric(+index) && +index >= 0) {
            //插入
            var goalRow = $(target).find('tr[coodo-grid-rowIndex=' + index + ']');
            if (goalRow.length) {
                if (index == 0)
                    trColls = $(target).find('tr');
                else
                    trColls = $(target).find('tr:gt(' + (index - 1) + ')');
                trColls.each(function () {
                    var rowIndex = +$(this).attr('coodo-grid-rowIndex') + 1;
                    $(this).attr('coodo-grid-rowIndex', rowIndex);
                    $(this).find('.coodo-grid-rowNumber').text(rowIndex + 1);
                });

                var rowResult = createRowData(target, row, index);

                goalRow.before(rowResult);

                gridData.rows.splice(index, 0, row);
                gridData.total++;

                initIndent(target);
            }
            else
                appendRow(target, row);
        }
    }

    function updateRow(target, index, row) {
        var state = $.data(target, 'grid');
        var dataTr = $(target).find('tr[coodo-grid-rowIndex=' + index + ']');
        if (dataTr.length) {
            $.extend(state.data.rows[index], row); //更新数据

            dataTr.find('td:not(.coodo-grid-rowNumber,.coodo-grid-checkBox)').each(function () {
                var field = $(this).attr('field');
                var column = getColumnOption(target, field);
                var fieldValue = row[field] || null;
                var dataDiv = $(this).find('>.coodo-grid-data');
                if (column && column.formatter)
                    dataDiv.html(column.formatter.call(dataDiv, fieldValue, row, index));
                else
                    dataDiv.attr('title', fieldValue).html(fieldValue);
            });
        }
    }

    function deleteRow(target, index) {
        var state = $.data(target, 'grid');
        var row = $(target).find('tr[coodo-grid-rowIndex=' + index + ']');
        if (row.length) {
            $(target).find('tr:gt(' + index + ')').each(function () {
                $(this).attr('coodo-grid-rowIndex', +$(this).attr('coodo-grid-rowIndex') - 1);
                $(this).find('.coodo-grid-rowNumber').each(function () {
                    $(this).text(+$(this).text() - 1);
                });
            });

            row.remove();
            var currentRowData = state.data.rows.splice(index, 1);
            state.data.total--;

            var k = $.inArray(currentRowData[0], state.selectRows);
            if (k >= 0) state.selectRows.splice(k, 1);

            initIndent(target);
        }
    }

    function beginEdit(target, index) {
        var state = $.data(target, 'grid');
        var opts = state.options;
        var row = $(target).find('tr[coodo-grid-rowindex=' + index + ']');
        if (!row.length) return;
        var cells = row.find('.coodo-grid-data-cell');

        if (opts.onBeforeEdit.call(row[0], index, state.data.rows[index]) == false)  return false;
        $.each(cells, function () {
            var field = getFieldProperty(opts.columns, $(this).attr('field'));
            if (field.editor && !$(this).find('.coodo-grid-data').next().length) {
                var editorType = field.editor.type || field.editor;
                var editorOptions = field.editor.options || {};
                var editor = $.fn.grid.defaults.editors[editorType];
                if (editor) {
                    $(this).addClass('cell-editing').find('>.coodo-grid-data').hide();
                    var cellEditor = $('<div class="cell-editor" />').appendTo(this);
                    cellEditor.append(editor.init(cellEditor, editorOptions));
                    editor.setValue(cellEditor, $(this).find('.coodo-grid-data').text());
                }
            }
        });
        opts.onBeginEdit.call(row[0], index, state.data.rows[index]);
    }

    function endEdit(target, index) {
        var state = $.data(target, 'grid');
        var opts = state.options;
        var row = $(target).find('tr[coodo-grid-rowindex=' + index + ']');
        if (!row.length) return;
        var cells = row.find('.coodo-grid-data-cell:has(>.cell-editor)');

        var values = {};
        $.each(cells, function () {
            var field = getFieldProperty(opts.columns, $(this).attr('field'));
            if (field.editor) {
                var editorType = field.editor.type || field.editor;
                var editor = $.fn.grid.defaults.editors[editorType];
                if (editor) {
                    var cellEditor = $(this).find('>.cell-editor');
                    var _value = editor.getValue(cellEditor);
                    $(this).find('>.coodo-grid-data').attr('title', _value).html(_value);
                    values[field.field] = _value;
                }
            }
        });
        values = $.isEmptyObject(values) ? undefined : values;

        opts.onEndEdit.call(row[0], index, state.data.rows[index], values);

        cells.removeClass('cell-editing').find('>.cell-editor').remove();
        cells.find('.coodo-grid-data').show();
        if (values) updateData(state.data, index, values);

        opts.onAfterEdit.call(row[0], index, state.data.rows[index], values);
    }

    function cancelEdit(target, index) {
        var state = $.data(target, 'grid');
        var opts = state.options;
        var row = $(target).find('tr[coodo-grid-rowindex=' + index + ']');
        row.find('>.cell-editing').removeClass('cell-editing');
        row.find('.cell-editor').remove();
        row.find('.coodo-grid-data').show();
        opts.onCancelEdit.call(row[0], index, state.data.rows[index]);
    }

    function getFieldProperty(columns, field) {
        var result = null;

        $.each(columns, function () {
            if ($.isArray(this))
                result = getFieldProperty(this, field);
            else if (this.field == field)
                result = this;

            if (result)
                return false;
        });

        return result;
    }

    function updateData(data, index, values) {
        var row = data.rows[index];
        if (row) {
            $.each(values, function (p, v) {
                row[p] = v;
            });
        }
    }

    function createColumnChoose(target) {
        var opts = $.data(target, 'grid').options;
        var columns = $.isArray(opts.columns[0]) ? opts.dataColumns : opts.columns;

        var drop = $('<div class="dropdown columnChoose" />');
        var btn = $('<button class="btn btn-default btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" />').appendTo(drop);
        btn.append('<span class="glyphicon glyphicon-th-list" />');

        var ul = $('<ul class="dropdown-menu dropdown-menu-right" />').appendTo(drop);
        $.each(columns, function () {
            if (this.field)
                ul.append('<li><a href="javascript:void(0);"><input type="checkbox" ' + (this.hidden ? '' : 'checked') + ' value="' + this.field + '" />' + this.title + '</a></li>');
        });

        drop.find('ul>li>a>input').click(function () {
            if (this.checked)
                $(target).grid('showColumn', $(this).val());
            else
                $(target).grid('hideColumn', $(this).val());
        });
        return drop;
    }

    function getRowIndex(target, row) {
        var state = $.data(target, 'grid');
        var rowIndex = -1;
        if (state && state.data && state.data.rows.length) {
            if (typeof row == 'object') {
                rowIndex = $.inArray(row, state.data.rows);
            }
            else
                $.each(state.data.rows, function (i) {
                    if (this[state.options.idField] == row) {
                        rowIndex = i;
                        return false;
                    }
                });
        }
        return rowIndex;
    }

    function getColumnOption(target, field) {
        var columns = $.data(target, 'grid').options.columns;
        var column;
        if ($.isArray(columns[0]))
            $.each(columns, function () {
                $.each(this, function () {
                    if (this.field == field) {
                        column = this;
                        return false;
                    }
                });
            });
        else
            $.each(columns, function () {
                if (this.field == field) {
                    column = this;
                    return false;
                }
            });

        return column;
    }

    function getEditor(target, index, field) {
        var opts = $.data(target, 'grid').options;
        var _fieldProperty = getFieldProperty(opts.columns, field);
        var editorType = _fieldProperty.editor.type || _fieldProperty.editor;
        var goalDom;
        if (editorType) {
            switch (editorType) {
                case "text":
                    goalDom = $(target).find('.coodo-grid-data-row:eq(' + index + '>.coodo-grid-data-cell[field="' + field + '"]>.cell-editor>:text:eq(0))');
                    break;
                case "textArea":
                    goalDom = $(target).find('.coodo-grid-data-row:eq(' + index + '>.coodo-grid-data-cell[field="' + field + '"]>.cell-editor>textArea:eq(0))');
                    break;
                case "checkbox":
                    goalDom = $(target).find('.coodo-grid-data-row:eq(' + index + '>.coodo-grid-data-cell[field="' + field + '"]>.cell-editor>:checkbox:eq(0))');
                    break;
                case "numberbox":
                    goalDom = $(target).find('.coodo-grid-data-row:eq(' + index + '>.coodo-grid-data-cell[field="' + field + '"]>.cell-editor>input[type="number"]:eq(0))');
                    break;
                case "select":
                    goalDom = $(target).find('.coodo-grid-data-row:eq(' + index + ')>.coodo-grid-data-cell[field="' + field + '"]>.cell-editor>.coodo-selectPicker:eq(0)');
                    break;
            }
        }
        if (goalDom && goalDom.length)
            return goalDom[0];
        else
            return null;
    }

    $.fn.grid = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.grid.methods[options];
            if (method)
                return $.fn.grid.methods[options](this, param);
            else
                return this.parents('.coodo-panel:eq(0)').panel(options, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('grid');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'grid', {
                    options: $.extend({}, $.fn.panel.defaults, $.fn.grid.defaults, $.parser.parseOptions(this), option),
                    selectRows: [],
                    data: {total: 0, rows: []}
                });
            init(this);
        });
    };
    $.fn.grid.methods = {
        options: function (jq) {
            return $.data(jq[0], 'grid').options;
        },
        getPanel: function (jq) {
            return jq.eq(0).parents('.coodo-grid-panel:eq(0)')[0];
        },
        getPager: function (jq) {
            return jq.eq(0).parents('.panel-body:eq(0)').find('>.coodo-pagination')[0];
        },
        getData: function (jq) {
            return $.data(jq[0], 'grid').data;
        },
        getChecked: function (jq) {
            var data = $.data(jq[0], 'grid').data;
            var result = [];
            var Checkeds = jq.eq(0).find('tr:has(>.coodo-grid-checkBox>:checked)');
            $.each(Checkeds, function () {
                result.push(data.rows[+$(this).attr('coodo-grid-rowindex')]);
            });
            return result;
        },
        getSelected: function (jq) {
            var rows = $.data(jq[0], 'grid').selectRows
            if (rows.length)
                return rows[0];
            else
                return null;
        },
        getSelections: function (jq) {
            return $.data(jq[0], 'grid').selectRows;
        },
        getRow: function (jq, index) {
            return $.data(jq[0], 'grid').data.rows[index];
        },
        getRowIndex: function (jq, row) {
            return getRowIndex(jq[0], row);
        },
        load: function (jq, param) {
            return jq.each(function () {
                var opts = $.data(this, 'grid').options;
                loadRemoteData(this, {pageNumber: 1, queryParams: param}, function (target, total) {
                    if (opts.pagination) $($(target).grid('getPager')).pagination('build', total);
                });
            });
        },
        reload: function (jq, param) {
            return jq.each(function () {
                loadRemoteData(this, {queryParams: param});
            });
        },
        loadData: function (jq, data) {
            return jq.each(function () {
                loadData(this, {
                    total: data ? (data['total'] || (data['rows'] ? data.rows.length : data.length)) : 0,
                    rows: data ? (data['rows'] || data) : []
                });
            });
        },
        selectRow: function (jq, idValue) {
            return jq.each(function () {
                selectOrUnSelectRecord(this, idValue, true);
            });
        },
        unselectRow: function (jq, idValue) {
            return jq.each(function () {
                selectOrUnSelectRecord(this, idValue);
            });
        },
        checkRow: function (jq, idValue) {
            return jq.each(function () {
                checkOrunCheckRow(this, idValue, true);
            });
        },
        uncheckRow: function (jq, idValue) {
            return jq.each(function () {
                checkOrunCheckRow(this, idValue, false);
            });
        },
        clearSelections: function (jq) {
            return jq.each(function () {
                var state = $.data(this, 'grid');
                state.selectRows.splice(0);
                $(this).find('tr>td.coodo-grid-checkBox>:checkbox').each(function () {
                    this.checked = false;
                });
                $(this).find('tr').removeClass('coodo-grid-data-row-selected');
                $(this).parent().prev('.table-header').find('>tbody>tr>td.coodo-grid-checkBox>:checkbox').prop("checked", false);
            });
        },
        appendRow: function (jq, row) {
            return jq.each(function () {
                appendRow(this, row);
            });
        },
        insertRow: function (jq, param) {
            return jq.each(function () {
                insertRow(this, param.index, param.row);
            });
        },
        updateRow: function (jq, param) {
            return jq.each(function () {
                updateRow(this, param.index, param.row);
            });
        },
        deleteRow: function (jq, index) {
            return jq.each(function () {
                deleteRow(this, index);
            });
        },
        showColumn: function (jq, field) {
            return jq.each(function () {
                var opts = $.data(this, 'grid').options;
                $.each(opts.columns, function () {
                    if ($.isArray(this)) {
                        $.each(this, function () {
                            if (!this.checkbox && this.field === field)
                                delete this['hidden'];
                        });
                    }
                    else {
                        if (!this.checkbox && this.field === field)
                            delete this['hidden'];
                    }
                });
                $(this).find('tr>td[field=' + field + ']').removeClass('hidden');
                $(this).parent().prev('.table-header').find('tr>td[field=' + field + ']').removeClass('hidden');
            });
        },
        hideColumn: function (jq, field) {
            return jq.each(function () {
                var opts = $.data(this, 'grid').options;
                $.each(opts.columns, function () {
                    if ($.isArray(this)) {
                        $.each(this, function () {
                            if (!this.checkbox && this.field === field)
                                this['hidden'] = true;
                        });
                    }
                    else {
                        if (!this.checkbox && this.field === field)
                            this['hidden'] = true;
                    }
                });
                $(this).find('tr>td[field=' + field + ']').addClass('hidden');
                $(this).parent().prev('.table-header').find('tr>td[field=' + field + ']').addClass('hidden');
            });
        },
        beginEdit: function (jq, index) {
            return jq.each(function () {
                beginEdit(this, index);
            });
        },
        endEdit: function (jq, index) {
            return jq.each(function () {
                endEdit(this, index);
            });
        },
        cancelEdit: function (jq, index) {
            return jq.each(function () {
                cancelEdit(this, index);
            });
        },
        getEditor: function (jq, param) {
            return getEditor(jq[0], param.index, param.field);
        }
    };
    $.fn.grid.defaults = {
        columns: undefined,
        dataColumns: undefined,
        idField: undefined,
        data: undefined,
        url: undefined,
        method: 'Get',
        rowNumbers: true,
        sortName: undefined,
        sortOrder: undefined,
        queryParams: undefined,
        singleSelect: false,
        checkOnSelect: true,
        selectOnCheck: true,
        disableSelect: false,
        loadMsg: 'loading......',
        noRecordMsg: '没有符合条件的记录！',
        striped: true,
        bordered: true,
        hover: true,
        condensed: false,
        pagination: false,
        pageSize: 10,
        pageNumber: 1,
        showPage: 5,
        toolbar: undefined,
        columnChoose: undefined,
        rowStyle: function (index, row) {
        },
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onClickCell: function (rowIndex, field, value) {

        },
        onDblClickCell: function (rowIndex, field, value) {
        },
        onClickRow: function (rowIndex, rowData) {
        },
        onDblClickRow: function (rowIndex, rowData) {
        },
        onSelect: function (rowIndex, rowData) {
        },
        onUnselect: function (rowIndex, rowData) {
        },
        onCheck: function (rowIndex, checked) {

        },
        onCheckAll: function (checked) {

        },
        onBeforeEdit: function (rowIndex, rowData) {
        },
        onBeginEdit: function (rowIndex, rowData) {

        },
        onEndEdit: function (rowIndex, rowData) {

        },
        onAfterEdit: function (rowIndex, rowData, changes) {
        },
        onCancelEdit: function (rowIndex, rowData) {
        },
        onSortColumn: function (sort, order) {

        }
    };
    $.fn.grid.defaults.editors = {
        text: {
            init: function (target) {
                var _input = $('<input type="text" class="form-control" />').click(function (e) {
                    e.stopPropagation();
                });
                return _input;
            },
            getValue: function (target) {
                return target.find('>input:eq(0)').val();
            },
            setValue: function (target, value) {
                //this.handle.val(value);
                target.find('>input:eq(0)').val(value);
            }
        },
        textArea: {
            init: function (target) {
                var _textArea = $('<textarea class="form-control" />').click(function (e) {
                    e.stopPropagation();
                });
                return _textArea;
            },
            getValue: function (target) {
                return target.find('>textarea:eq(0)').val();
            },
            setValue: function (target, value) {
                target.find('>textarea:eq(0)').val(value);
            }
        },
        checkbox: {
            init: function (target) {
                var _checkbox = $('<input type="checkbox" />').click(function (e) {
                    e.stopPropagation();
                });
                return _checkbox;
            },
            getValue: function (target) {
                return target.find('>:checkbox:eq(0)').prop('checked') + "";
            },
            setValue: function (target, value) {
                target.find('>:checkbox:eq(0)').prop('checked', $.parseBool(value));
            }
        },
        numberbox: {
            init: function (target) {
                var _numberBox = $('<input type="number" class="form-control" />').click(function (e) {
                    e.stopPropagation();
                });
                return _numberBox;
            },
            getValue: function (target) {
                return +target.find('>input[type="number"]:eq(0)').val();
            },
            setValue: function (target, value) {
                target.find('>input[type="number"]:eq(0)').val(+value);
            }
        },
        select: {
            init: function (target, options) {
                var _select = $('<select />').appendTo(target);
                _select.selectPicker(options);
            },
            getValue: function (target) {
                return target.find('>.coodo-selectPicker:eq(0)').selectPicker('getText');
            },
            setValue: function (target, value) {
                target.find('>.coodo-selectPicker:eq(0)').selectPicker('select', value);
            }
        }
    };
    $.fn.grid.columnDefaults = {
        checkbox: undefined,
        title: undefined,
        field: undefined,
        mfield: undefined,
        sortable: undefined,
        width: undefined,
        maxWidth: undefined,
        align: undefined,
        halign: undefined,
        hidden: undefined,
        merge: false,
        rowSpan: undefined,
        colSpan: undefined,
        formatter: undefined,
        editor: undefined,
        styler: undefined
    };
}(jQuery);
//propertyGrid
+function ($) {

    function init(target){
        var state = $(target).data('propertyGrid');
        var opts = state.options;
        $(target).addClass('coodo-propertyGrid');

        $(target).grid($.extend(opts, {
            onClickRow: function (rowIndex, rowData) {
                if(!$(this).find('.cell-editing').length) {
                    opts.columns[2].editor = rowData.editor;
                    $(target).grid('beginEdit', rowIndex);
                }
            },
            onUnselect: function (rowIndex, rowData) {
                $(target).grid('endEdit', rowIndex);
            },
            onBeforeEdit: function (rowIndex, rowData) {
                state.currentIndex = rowIndex;
            },
            onAfterEdit: function (rowIndex, rowData, changes) {
                state.currentIndex = undefined;
            },
            onLoadSuccess: function(data){
                if(opts.showGroup){//显示分组
                    showGroup(target, data);
                }
                sortGroup(target, data);
            }
        }));

        $(document).off('.propertygrid').on('mousedown.propertygrid', function(e){
            var p = $(e.target).parents('.coodo-propertyGrid');
            if(!p.length){
                $(target).grid('endEdit', state.currentIndex);
            }
        });
    }

    function showGroup(target, data) {
        var state = $(target).data('propertyGrid');
        var opts = state.options;
        var groups = [];
        for (var i = 0; i < data.rows.length; i++) {
            var row = data.rows[i];
            var group = getGroup(row[opts.groupField]);
            if (!group) {
                group = {
                    value: row[opts.groupField],
                    rows: [row]
                };
                groups.push(group);
            } else {
                group.rows.push(row);
            }
        }
        state.groups = groups;

        var groupIndex = 0;
        for (var i = 0; i < groups.length; i++) {
            var group = groups[i];
            var row = $(target).find('tr.coodo-grid-data-row:eq(' + groupIndex + ')');
            var groupRow = $('<tr class="coodo-grid-group"></tr>').attr('coodo-grid-group-index', i).insertBefore(row);
            var groupIcon = $('<td class="coodo-grid-group-cell coodo-grid-group-expand"><i class="glyphicon glyphicon-minus"></i></td>').attr('rowspan', group.rows.length + 1).width(opts.columns[0].width).appendTo(groupRow);
            var groupTitle = $('<td class="coodo-grid-group-cell" colspan="2"></td>').appendTo(groupRow);
            if(opts.groupFormatter) {
                groupTitle.append(opts.groupFormatter.call(target, group.value, group.rows));
            } else {
                groupTitle.append(group.value);
            }
            $.each(group.rows, function (i) {
                var trRow = $(target).find('tr.coodo-grid-data-row:eq(' + groupIndex + ')');
                trRow.find('td:eq(0)').hide();
                groupIndex++;
            });

            groupIcon.on('click','>i', function () {
                var currentGroupIndex = +$(this).parents('.coodo-grid-group').attr('coodo-grid-group-index');
                if ($(this).parent().hasClass('coodo-grid-group-expand')) {
                    collapseGroup(target, currentGroupIndex);
                } else {
                    expandGroup(target, currentGroupIndex);
                }
            });
        }
        function getGroup(value) {
            for (var i = 0; i < groups.length; i++) {
                var group = groups[i];
                if (group.value == value) {
                    return group;
                }
            }
            return null;
        }
    }

    function sortGroup(target, data) {
        var state = $(target).data('propertyGrid');
        var opts = state.options;

        //列添加排序
        var rows = $(target).find('.coodo-grid-header-row');
        var column = rows.find('td:eq(1)');
        var sortOrder = column.attr('coodo-group-grid-sort');
        if(!sortOrder){
            column.attr('coodo-group-grid-sort', "");
        }
        if(!column.find('>div>.btn-group').length){
            column.find('>div').append($('<div class="btn-group dropup"><span>&nbsp;</span></div>'));
        }

        //绑定事件
        $(target).off('.propertygrid').on('click.propertygrid', '.coodo-grid-header-row>td[coodo-group-grid-sort]', function () {
            var order = "asc";
            var sortFlag = $(this).find('.btn-group');

            switch ($(this).attr('coodo-group-grid-sort')) {
                case "":
                case "desc":
                    sortFlag.addClass('dropup');
                    break;
                case "asc":
                    sortFlag.removeClass('dropup');
                    order = "desc";
                    break;
            }

            sortFlag.find('span').addClass('caret');
            $(this).attr('coodo-group-grid-sort', order);

            if(opts.showGroup) {
                var newArr = [];
                $.each(state.groups, function () {
                    this.rows.sort(function (a, b) {
                        if(order == 'asc'){
                            return a.name.localeCompare(b.name);
                        } else {
                            return b.name.localeCompare(a.name);
                        }
                    });
                    newArr = newArr.concat(this.rows);
                });
                $(target).grid('loadData',{total:newArr.length,rows:newArr});
            } else {
                data.rows.sort(function (a, b) {
                    if(order == 'asc'){
                        return a.name.localeCompare(b.name);
                    } else {
                        return b.name.localeCompare(a.name);
                    }
                });
                $(target).grid('loadData',data);
            }
        });
    }

    function expandGroup(target, groupIndex) {
        var state = $(target).data('propertyGrid');
        var currentTarget = $(target).find('tr.coodo-grid-group:eq(' + groupIndex + ')').find('td.coodo-grid-group-cell:eq(0)');
        var currentGroupData = state.groups[groupIndex].rows;
        $.each(currentGroupData, function (i) {
            if (groupIndex > 0) {
                var currentIndex = i + state.groups[groupIndex - 1].rows.length;
                var trRow = $(target).find('tr.coodo-grid-data-row:eq(' + currentIndex + ')');
                trRow.show();
            } else {
                var trRow = $(target).find('tr.coodo-grid-data-row:eq(' + i + ')');
                trRow.show();
            }
        });

        currentTarget.removeClass('coodo-grid-group-collapse').addClass('coodo-grid-group-expand');
        currentTarget.find('i').removeClass().addClass('glyphicon glyphicon-minus');
        currentTarget.attr('rowspan', currentGroupData.length + 1);
    }

    function collapseGroup(target, groupIndex) {
        var state = $(target).data('propertyGrid');
        var currentTarget = $(target).find('tr.coodo-grid-group:eq(' + groupIndex + ')').find('td.coodo-grid-group-cell:eq(0)');
        var currentGroupData = state.groups[groupIndex].rows;
        $.each(currentGroupData, function (i) {
            if (groupIndex > 0) {
                var currentIndex = i + state.groups[groupIndex - 1].rows.length;
                var trRow = $(target).find('tr.coodo-grid-data-row:eq(' + currentIndex + ')');
                trRow.hide();
            } else {
                var trRow = $(target).find('tr.coodo-grid-data-row:eq(' + i + ')');
                trRow.hide();
            }
        });
        currentTarget.removeClass('coodo-grid-group-expand').addClass('coodo-grid-group-collapse');
        currentTarget.find('i').removeClass().addClass('glyphicon glyphicon-plus');
        currentTarget.removeAttr('rowspan');
    }

    $.fn.propertyGrid = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.propertyGrid.methods[options];
            if (method)
                return $.fn.propertyGrid.methods[options](this, param);
            else
                return $(this).grid(options, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('propertyGrid');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'propertyGrid', {
                    options: $.extend({}, $.fn.panel.defaults, $.fn.grid.defaults, $.fn.propertyGrid.defaults, $.parser.parseOptions(this), option),
                    currentIndex: undefined,
                    groups: []
                });
            init(this);
        });

    };
    $.fn.propertyGrid.defaults = {
        width: 400,
        rowNumbers: false,
        singleSelect: true,
        columns: [
            {title: '', width: 20},
            {field: 'name', title: 'name'},
            {field: 'value', title: 'value'}
        ],
        showGroup: false,
        groupField: 'group',
        groupFormatter: undefined
    };
    $.fn.propertyGrid.methods = {
        options: function (jq) {
            return $.data(jq[0], 'propertyGrid').options;
        },
        getData: function (jq) {
            var currentIndex = jq.eq(0).data('propertyGrid').currentIndex;
            jq.eq(0).grid('endEdit', currentIndex);
            return jq.eq(0).grid('getData');
        },
        expandGroup: function (jq, groupIndex) {
            return jq.each(function () {
                var opts = $.data(this, 'propertyGrid').options;
                if(opts.showGroup) {
                    expandGroup(this, groupIndex);
                }
            });
        },
        collapseGroup: function (jq, groupIndex) {
            return jq.each(function () {
                var opts = $.data(this, 'propertyGrid').options;
                if(opts.showGroup) {
                    collapseGroup(this, groupIndex);
                }
            });
        }
    };
}(jQuery);
//treeView
+function ($) {
    function init(target) {
        var opts = $.data(target, 'treeView').options;
        $(target).addClass("coodo-treeView coodoTree");
        initAttr(target);
        initEvent(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'treeView').options;
        var lisData = getLiData($(target).children());
        if (!opts.lines) {
            $(target).addClass("coodoTriangular");
        } else {
            $(target).removeClass("coodoTriangular");
        }
        if (lisData.length) {
            loadData(target, lisData);
        }
        else if (opts.data) {
            loadData(target, opts.data);
        } else if (opts.url) {
            loadRemoteData(target, null, function (data) {
                loadData(this, data);
            });
        }
    }

    function initEvent(target) {
        var state = $.data(target, 'treeView');
        var opts = state.options;

        $(target).off('.treeView')
            .on('click.treeView', '.node>.nodeContent', function (e) {
                e.stopPropagation();
                var nodeContent = $(this);
                var node = getNode(state.data, nodeContent.attr('node-id'));
                opts.onClick.call(this, node);
                if (state.selectedNode == null || state.selectedNode != node)
                    selectNode(target, nodeContent, node);
            }) //click node
            .on('dblclick.treeView', '.node>.nodeContent', function (e) {
                e.stopPropagation();
                opts.onDblClick.call(this, getNode(state.data, $(this).attr('node-id')));
            })  //dblClick node
            .on('click.treeView', '.node>.nodeContent>.nodeHit', function (e) {
                e.stopPropagation();
                var treeNode = $(this).parents('.node:eq(0)');
                var nodeContent = $(this).parent();
                var node = getNode(state.data, nodeContent.attr('node-id'));
                if (!treeNode.hasClass('nodeLeaf')) {
                    if (treeNode.hasClass('nodeExpand')) {
                        collapse(target, treeNode);
                        opts.onCollapse.call(nodeContent[0], node);
                    }
                    else {
                        expand(target, treeNode, node);
                    }
                }
            })  //click hit
            .on('click.treeView', '.node>.nodeContent>.nodeCheckbox', function (e) {
                e.stopPropagation();
                var nodeContent = $(this).parent();
                var checked = true;
                if ($(this).hasClass('nodeCheckboxSelected'))
                    checked = false;
                checkNodeById(target, nodeContent.attr('node-id'), checked);
            })//click checkbox
            .on('blur.treeView','.node>.nodeContent>.nodeTitle>:text',function(){
                endEdit(target,$(this).parents('.nodeContent')[0]);
            });//end editing while input lose focus
    }

    function loadRemoteData(target, para, fnc) {
        var opts = $.data(target, 'treeView').options;
        var param = para || {};
        if (opts.url) {
            $.ajax({
                url: opts.url,
                method: opts.method,
                data: param,
                dataType: 'json',
                success: function (data) {
                    if (fnc)
                        fnc.call(target, data);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
                }
            });
        }
        else {
            if (fnc)
                fnc.call(target, null);
        }
    }

    function loadData(target, data, parentNode) {
        var state = $.data(target, 'treeView');
        if (!state) return;//dom数据已丢失，停止加载
        var opts = state.options;
        clearData(target);
        if (data && data.length) {
            loadNodeData(target, data, parentNode);
            state.data = data;
        }
        opts.onLoadSuccess.call(target, data);
    }

    function loadNodeData(target, data, parentNode, l) {
        var state = $.data(target, 'treeView');
        var opts = state.options;
        var level = l || 0;

        $.each(data, function (i) {
            var node = $.extend({}, $.fn.treeView.nodeDefaults, this);

            var treeNode = $('<li class="node"/>').appendTo(parentNode || target);
            createNode(target, this, treeNode, level);
            if (node.children) {
                var childrenNode = $('<ul class="coodoTree"/>').appendTo(treeNode);
                if (node.expand)
                    treeNode.addClass('nodeExpand');
                else
                    collapse(target, treeNode);

                loadNodeData(target, node.children, childrenNode, level + 1);
                if (!opts.lines)
                    childrenNode.addClass('coodoTriangular').find('.indent').removeClass('treeLine');
            }
            else if (!node.open)
                treeNode.addClass('nodeCollapse');
            else
                treeNode.addClass('nodeLeaf');

            if (i + 1 == data.length)
                treeNode.find('.coodoTree .nodeContent>i:nth-child(' + (level + 1) + ')').removeClass('treeLine');
        });
    }

    function createNode(target, node, treeNode, level) {
        var state = $.data(target, 'treeView');
        var opts = state.options;
        var nodeData = $.extend({}, $.fn.treeView.nodeDefaults, node);

        //node
        var nodeContent = $('<div class="nodeContent" />')
            .attr({'node-id': (nodeData.id == undefined ? nodeData.text : nodeData.id), 'node-open': nodeData.open})
            .appendTo(treeNode);
        node.target = nodeContent[0];

        //count indent
        for (var i = 0; i < level; i++)
            nodeContent.append($('<i class="indent treeLine" />'));

        //hit
        nodeContent.append('<i class="nodeHit" />');

        //checkbox
        if (opts.checkbox) {
            if (typeof opts.checkbox == 'function') {
                if (opts.checkbox.call(target, node))
                    nodeContent.append('<i class="nodeCheckbox" />');
            }
            else if (opts.checkbox && (!opts.onlyLeafCheck || !node.children)) {
                nodeContent.append('<i class="nodeCheckbox" />');
            }

            if (node.check) checkNode(target, nodeContent, true);
        }

        //icon
        if (opts.icon) {
            var icon = $('<i />').appendTo(nodeContent);
            if (nodeData.iconCls)
                icon.addClass(nodeData.iconCls);
            else if (nodeData.iconCls + '' == 'null')
                icon.addClass('hidden');
            else
                icon.addClass('nodeIcon')
        }

        //content
        var nodeSpan = $('<span class="nodeTitle" />').appendTo(nodeContent);
        if (opts.formatter)
            nodeSpan.append(opts.formatter.call(nodeSpan, nodeData.text, node));
        else
            nodeSpan.append(nodeData.text);
    }

    function getNode(data, id) {
        var result = null;
        var child = [];
        for (var i = 0; i < data.length; i++) {
            if (data[i].id == id || data[i].text == id)
                result = data[i];
            else if (data[i].children)
                $.each(data[i].children, function () {
                    child.push(this);
                });

            if (result)
                break;
        }
        if (!result && child.length)
            return getNode(child, id);
        else
            return result;
    }

    function getNodeDom(target, id) {
        return $(target).find('.nodeContent[node-id=' + id + ']').parent('.node');
    }

    function collapse(target, treeNode) {
        var opts = $.data(target, 'treeView').options;

        treeNode.removeClass('nodeExpand').addClass('nodeCollapse');
        if (opts.animation)
            treeNode.find('>.coodoTree').slideUp();
        else
            treeNode.find('>.coodoTree').hide();
    }

    function expand(target, treeNode, node) {
        var state = $.data(target, 'treeView');
        var opts = state.options;

        treeNode.removeClass('nodeCollapse');
        var nodeContent = treeNode.find('.nodeContent');

        //async load child node
        if (!$.parseBool(nodeContent.attr('node-open')) && !treeNode.find('>.coodoTree').length) {
            treeNode.addClass('nodeLoading');

            var childNode = $('<ul class="coodoTree">').appendTo(treeNode);
            loadRemoteData(target, {id: nodeContent.attr('node-id')}, function (data) {
                if (data) {
                    var curLevel = treeNode.find('.nodeContent>.indent').length;
                    loadNodeData(target, data, childNode, curLevel + 1);
                    updateNodeIndent(treeNode);
                }

                if (opts.animation)
                    treeNode.find('>.coodoTree').slideDown();
                else
                    treeNode.find('>.coodoTree').show();

                treeNode.removeClass('nodeLoading').addClass('nodeExpand');

                node.children = data;
                opts.onExpand.call(nodeContent[0], node);
            });
        }
        else {
            if (opts.animation)
                treeNode.find('>.coodoTree').slideDown();
            else
                treeNode.find('>.coodoTree').show();

            treeNode.addClass('nodeExpand');

            opts.onExpand.call(nodeContent[0], node);
        }
    }

    function selectNode(target, nodeContent, node) {
        var state = $.data(target, 'treeView');
        var opts = state.options;
        if (!node) node = getNode(state.data, nodeContent.attr('node-id'));
        $(target).find('.nodeSelected').removeClass('nodeSelected');
        nodeContent.addClass('nodeSelected');
        state.selectedNode = node;
        opts.onSelect.call(nodeContent[0], node);
    }

    function checkNode(target, nodeContent, checked) {
        var opts = $.data(target, 'treeView').options;
        var nodeCbx = nodeContent.find('>.nodeCheckbox');

        nodeCbx.removeClass('nodeCheckboxPreSelected');
        if (checked) {
            //checked
            nodeCbx.addClass('nodeCheckboxSelected');
            if (opts.cascadeCheck) nodeContent.next('.coodoTree').find('.nodeCheckbox').addClass('nodeCheckboxSelected');
        }
        else {
            //unChecked
            nodeCbx.removeClass('nodeCheckboxSelected');
            if (opts.cascadeCheck) nodeContent.next('.coodoTree').find('.nodeCheckbox').removeClass('nodeCheckboxSelected');
        }

        if (opts.cascadeCheck) {
            //级联选中父节点的状态
            var parentNodes = nodeContent.parents('.coodoTree').prevAll();
            $.each(parentNodes, function () {
                var currentCheckbox = $(this).find('.nodeCheckbox');
                var childNodesBox = $(this).next().find('.nodeCheckbox');
                var selectedNodes = childNodesBox.filter('.nodeCheckboxSelected');

                if (!selectedNodes.length)
                    currentCheckbox.removeClass('nodeCheckboxPreSelected').removeClass('nodeCheckboxSelected')
                else if (childNodesBox.length == selectedNodes.length)
                    currentCheckbox.removeClass('nodeCheckboxPreSelected').addClass('nodeCheckboxSelected');
                else
                    currentCheckbox.removeClass('nodeCheckboxSelected').addClass('nodeCheckboxPreSelected');
            });
        }
    }

    function checkNodeById(target, id, checked) {
        var state = $.data(target, 'treeView');
        var opts = state.options;
        var data = state.data;
        var nodeContent = $(target).find('.nodeContent[node-id=' + id + ']');
        var node = getNode(data, nodeContent.attr('node-id'));
        if (nodeContent.length && node) {
            if (!node.target) node.target = nodeContent[0];
            checkNode(target, nodeContent, checked);
            opts.onCheck.call(nodeContent[0], node, checked);
        }
    }

    function appendNode(target, param) {
        var state = $.data(target, 'treeView');
        var opts = state.options;
        var treeNode = getNodeDom(target, param.id);
        treeNode.addClass('nodeLoading');
        if (param.id) {
            var childNode = treeNode.find('>.coodoTree');
            if (!childNode.length) {
                childNode = $('<ul class="coodoTree"/>').appendTo(treeNode);
                if (!opts.lines) {
                    childNode.addClass('coodoTriangular');
                }
            }
            var lastNotLeafNode = childNode.find('>.node:not(.nodeLeaf):last-child');
            var curLevel = treeNode.find('>.nodeContent>.indent').length;
            loadNodeData(target, param.data, childNode, curLevel + 1);
            updateNodeIndent(treeNode);
            //deal last notLeaf node
            if (lastNotLeafNode.length)
                lastNotLeafNode.find('.coodoTree .nodeContent .indent:nth-child(' + (curLevel + 2) + ')').addClass('treeLine');

            var node = getNode(state.data, param.id);
            if (node.children)
                node.children = node.children.concat(param.data);
            else
                node.children = param.data;
        }
        else {
            loadNodeData(target, param.data);
            state.data = state.data.concat(param.data);
        }
        treeNode.removeClass('nodeLeaf nodeLoading').addClass('nodeExpand');
    }

    function insertNode(target, param) {
        if (!param.before && !param.after)
            return false;

        var state = $.data(target, 'treeView');
        var opts = state.options;
        var id = param.before || param.after;
        var goalNode = getNodeDom(target, id); //li
        var level = goalNode.find('>.nodeContent>.indent').length;
        var parentId = goalNode.parent().prev().attr('node-id');
        var parentNodeData = getNode(state.data, parentId).children;

        $.each(param.data, function (i, n) {
            var node = $.extend({}, $.fn.treeView.nodeDefaults, n);
            var treeNode = $('<li class="node"/>');
            createNode(target, node, treeNode, level);
            if (node.children) {
                var newNodeChild = $('<ul />').addClass('coodoTree').appendTo(treeNode);
                if (!opts.lines) {
                    newNodeChild.addClass('coodoTriangular');
                }
                if (node.expand)
                    treeNode.addClass('nodeExpand');
                else
                    collapse(target, treeNode);

                loadNodeData(target, node.children, newNodeChild, level + 1);
            }
            else if (!node.open)
                treeNode.addClass('nodeCollapse');
            else
                treeNode.addClass('nodeLeaf');

            if (param.before)
                goalNode.before(treeNode);
            else {
                if (!goalNode.next().length)
                    goalNode.find('.coodoTree .nodeContent .indent:nth-child(' + (level + 1) + ')').addClass('treeLine');
                goalNode.after(treeNode);
            }
            updateNodeIndent(treeNode);
        });

        if (parentNodeData) {
            var j = 0;
            for (; j < parentNodeData.length; j++) {
                var obj = parentNodeData[j];
                if (obj.id == id) {
                    break;
                }
            }

            for (var h = 0; h < param.data.length; h++) {
                if (param.before) {
                    parentNodeData.splice(j, 0, param.data[h]);
                } else {
                    parentNodeData.splice(j + 1, 0, param.data[h]);
                }
                j++;
            }
            parentNodeData.children = parentNodeData;
        }
    }

    function updateNode(target, param) {
        if (!param.id)
            return false;

        var state = $.data(target, 'treeView');
        var nodeDom = getNodeDom(target, param.id); //li
        var parentId = nodeDom.parent().prev().attr('node-id');
        var parentNodeData;
        if (parentId) {
            parentNodeData = getNode(state.data, parentId).children;
            nodeDom.parent().prev().find('>.nodeTitle').html(param.data.text);
        } else {
            parentNodeData = state.data;
            nodeDom.find('.nodeContent[node-id=' + param.id + ']').find('>.nodeTitle').html(param.data.text);
        }

        if (parentNodeData) {
            for (var j = 0; j < parentNodeData.length; j++) {
                var obj = parentNodeData[j];
                if (obj.id == param.id) {
                    obj.text = param.data.text;
                    obj.attributes = param.data.attributes;
                    obj.iconCls = param.data.iconCls;
                    break;
                }
            }
            if (parentId) {
                getNode(state.data, parentId).children = parentNodeData;
            } else {
                state.data = parentNodeData;
            }
        }
    }

    function removeNode(target, id) {
        var state = $.data(target, 'treeView');
        var nodeDom = getNodeDom(target, id); //li
        var parentId = nodeDom.parent().prev().attr('node-id');
        var parentNodeData = state.data;
        if (parentId) {
            parentNodeData = getNode(state.data, parentId).children;
        }
        var prevNode = nodeDom.prev();
        nodeDom.remove();
        updateNodeIndent(prevNode);

        for (var j = 0; j < parentNodeData.length; j++) {
            var obj = parentNodeData[j];
            if (obj.id == id) {
                parentNodeData.splice(j, 1);
            }
        }
        if (parentId && !parentNodeData.length)
            getNodeDom(target, parentId).removeClass('nodeExpand nodeCollapse').addClass('nodeLeaf');
    }

    function clearData(target) {
        var state = $.data(target, 'treeView');
        state.selectedNode = state.data = null;
        $(target).children().remove();
    }

    function updateNodeIndent(treeNode) {
        var level = 0;
        //current node
        if (!treeNode.next().length) {
            level = treeNode.find('>.nodeContent>.indent').length;
            treeNode.find('.coodoTree .nodeContent .indent:nth-child(' + (level + 1) + ')').removeClass('treeLine');
        }
        //all parent node
        treeNode.parents('.node').each(function () {
            if (!$(this).next().length) {
                level = $(this).find('>.nodeContent>.indent').length;
                $(this).find('.coodoTree .nodeContent .indent:nth-child(' + (level + 1) + ')').removeClass('treeLine');
            }
            else
                return false;
        });
    }

    function getLiData(lis) {
        var data = [];
        if (lis.length) {
            $.each(lis, function () {
                var node = $.extend({}, $.fn.treeView.nodeDefaults, {
                    text: $(this).children('span').text()
                });
                var childLis = $(this).find('>ul>li');
                if (childLis.length)
                    node['children'] = getLiData(childLis);

                data.push(node);
            });
        }
        return data;
    }

    function beginEdit(target, nodeEl) {
        var state = $.data(target, 'treeView');
        var opts = state.options, data = state.data;
        var node = getNode(data, $(nodeEl).attr('node-id'));
        var nodeTitle = $(nodeEl).find('.nodeTitle');
        if (opts.onBeforeEdit.call(nodeEl, node)==false) return;
        nodeTitle.html($('<input type="text" class="form-control">').val(nodeTitle.text()));
        nodeTitle.find(':text').focus();
    }

    function endEdit(target, nodeEl) {
        var state = $.data(target, 'treeView');
        var opts = state.options, data = state.data;
        var node = getNode(data, $(nodeEl).attr('node-id'));
        var nodeTitle = $(nodeEl).find('.nodeTitle');
        node.text = nodeTitle.find(':text').val();
        nodeTitle.html(nodeTitle.find(':text').val());

        opts.onAfterEdit.call(nodeEl, node);
    }

    function cancelEdit(target, nodeEl) {
        var state = $.data(target, 'treeView');
        var opts = state.options, data = state.data;
        var node = getNode(data, $(nodeEl).attr('node-id'));
        var nodeTitle = $(nodeEl).find('.nodeTitle');
        nodeTitle.html(node.text);

        opts.onCancelEdit.call(nodeEl, node);
    }

    $.fn.treeView = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.treeView.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('treeView');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'treeView', {
                    options: $.extend({}, $.fn.treeView.defaults, $.parser.parseOptions(this), option),
                    data: [],
                    selectedNode: null
                });

            init(this);
        });
    };
    $.fn.treeView.methods = {
        options: function (jq) {
            return $.data(jq[0], 'treeView').options;
        },
        getData: function (jq) {
            return $.data(jq[0], 'treeView').data;
        },
        getNode: function (jq, id) {
            var data = $.data(jq[0], 'treeView').data;
            return getNode(data, id);
        },
        getSelected: function (jq) {
            return $.data(jq[0], 'treeView').selectedNode;
        },
        getChecked: function (jq) {
            var data = $.data(jq[0], 'treeView').data;
            var result = [];

            $(jq[0]).find('.nodeCheckboxSelected').each(function () {
                var nodeId = $(this).parent().attr('node-id');
                var node = getNode(data, nodeId);
                if (!node.target)
                    node.target = $(this).parent()[0];
                result.push(node);
            });
            return result;
        },
        getParent: function (jq, nodeDom) {
            var data = $.data(jq[0], 'treeView').data;
            if (nodeDom) {
                var parentNodeDom = $(nodeDom).parent().parent().prev('.nodeContent');
                if (parentNodeDom.length) {
                    var parentNode = getNode(data, parentNodeDom.eq(0).attr('node-id'));
                    if (!parentNode.target) parentNode.target = parentNodeDom[0];
                    return parentNode;
                }
                else
                    return null;
            } else {
                return null;
            }
        },
        isLeaf: function (jq, nodeDom) {
            if (nodeDom && $(nodeDom).parent().hasClass('nodeLeaf')) {
                return true;
            } else {
                return false;
            }
        },
        loadData: function (jq, data) {
            return jq.each(function () {
                loadData(this, data);
            });
        },
        reload: function (jq, nodeDom) {
            return jq.each(function () {
                if (nodeDom) {

                    var data = $.data(this, 'treeView').data;
                    var node = getNode(data, $(nodeDom).attr('node-id'));
                    var treeNode = $(nodeDom).parent();
                    treeNode.addClass('nodeLoading');

                    loadRemoteData(target, {id: node.id}, function (data) {
                        var childNodes = treeNode.find('.coodoTree');
                        if (!childNodes.length) {
                            childNodes = $('<ul class="coodoTree" />').appendTo(treeNode);
                            treeNode.removeClass('nodeLeaf').addClass('nodeExpand');
                        }
                        else
                            childNodes.children().remove();

                        var curLevel = treeNode.find('.nodeContent>.indent').length;
                        loadNodeData(target, data, childNodes, curLevel + 1);
                        if (!treeNode.next().length)
                            treeNode.find('.coodoTree .nodeContent .indent:nth-child(n+' + curLevel + ')').removeClass('treeLine');

                        treeNode.removeClass('nodeLoading').addClass('nodeExpand');
                        node.children = data;
                    });
                }
                else
                    loadRemoteData(this, null, function (data) {
                        loadData(this, data);
                    });
            });
        },
        select: function (jq, id) {
            return jq.each(function () {
                var nodeContent = $(this).find('.nodeContent[node-id=' + id + ']');
                if (nodeContent.length) {
                    selectNode(this, nodeContent);
                }
            });
        },
        check: function (jq, id) {
            return jq.each(function () {
                checkNodeById(this, id, true);
            });
        },
        uncheck: function (jq, id) {
            return jq.each(function () {
                checkNodeById(this, id, false);
            });
        },
        append: function (jq, param) {
            return jq.each(function () {
                appendNode(this, param);
            });
        },
        insert: function (jq, param) {
            return jq.each(function () {
                insertNode(this, param);
            });
        },
        remove: function (jq, id) {
            return jq.each(function () {
                removeNode(this, id);
            });
        },
        beginEdit: function (jq, nodeEl) {
            beginEdit(jq[0], nodeEl);
            return jq;
        },
        endEdit: function (jq, nodeEl) {
            endEdit(jq[0], nodeEl);
            return jq;
        },
        cancelEdit: function (jq, nodeEl) {
            cancelEdit(jq[0], nodeEl);
            return jq;
        }

        /* update: function (jq, param) {
         jq.each(function () {
         updateNode(this, param);
         });
         }*/
    };
    $.fn.treeView.defaults = {
        animation: true,
        onlyLeafCheck: false,
        url: undefined,
        method: 'Get',
        icon: true,
        checkbox: false,
        cascadeCheck: true,
        data: undefined,
        lines: true,
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onClick: function (node) {
        },
        onDblClick: function (node) {
        },
        onExpand: function (node) {
        },
        onCollapse: function (node) {
        },
        onSelect: function (node) {
        },
        onCheck: function (node, checked) {
        },
        onBeforeEdit: function (node) {

        },
        onAfterEdit: function (node) {

        },
        onCancelEdit: function (node) {

        }
    };
    $.fn.treeView.nodeDefaults = {
        id: undefined,
        text: undefined,
        children: undefined,
        iconCls: undefined,
        check: false,
        expand: false,
        open: true,
        target: undefined
    };
}(jQuery);
//selectPicker
+function ($) {
    function init(target) {
        $(target).addClass('coodo-selectPicker');
        $(target).hide();
        createView(target);
        initAttr(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'selectPicker').options;
        if (opts.multiple) $(target).attr('multiple', true);

        //呈现下拉列表
        var options;
        if (opts.data.length) {
            loadData(target, opts.data, true);
        }
        else if ((options = $(target).children()).length) {
            var data = [];
            $.each(options, function () {
                var i = $(this);
                var iData = {
                    disabled: i.attr('disabled') || false,
                    selected: i.attr('selected') ? true : false
                };

                if (i.is("optgroup")) {
                    $.extend(iData, {group: i.attr('label') || '', options: []});
                    i.children().each(function () {
                        var childData = {
                            disabled: $(this).attr('disabled') || false,
                            selected: $(this).attr('selected') ? true : false
                        };
                        childData[opts.valueField] = $(this).attr('value') == undefined ? $(this).text() : $(this).attr('value');
                        childData[opts.textField] = $(this).text();
                        iData.options.push(childData);
                    });
                }
                else {
                    iData[opts.valueField] = i.attr('value') == undefined ? i.text() : i.attr('value');
                    iData[opts.textField] = i.text();
                }
                data.push(iData);
            });
            loadData(target, data);
        }
        else {
            loadRemoteData(target);
        }

        var drop = $(target).prev('.coodo-selectPicker-list'); //取得下拉列表对象
        //var dropToggle=drop.find('>.dropdown-toggle');
        var menu = drop.find('.dropdown-menu');
        var menuConent = menu.find('li.coodo-selectPicker-content>ul');
        if (opts.upward) {
            drop.removeClass('dropdown').addClass('dropup');
        } else {
            drop.removeClass('dropup').addClass('dropdown');
        }
        if (opts.width) {
            drop.width(opts.width);
            drop.find('>.dropdown-toggle > .coodo-selectPicker-text').css('padding-right', '10px');
            menu.css('width', '100%');
        }
        if (opts.height) {
            menuConent.css('maxHeight', opts.height);
        }
        if (opts.search) {
            if (!menu.find('.coodo-selectPicker-search').length)
                menu.prepend(createSearch(target, menuConent));
        } else {
            menu.find('.coodo-selectPicker-search').remove();
        }
        if (opts.disabled) {
            disabled(target);
        } else {
            enabled(target);
        }
    }

    function initEvent(target) {
        var state = $.data(target, 'selectPicker')
        var opts = state.options;
        var drop = $(target).prev('.coodo-selectPicker-list');

        drop.off('.dropdown .selectPicker')
            .on("shown.bs.dropdown", function () {
                drop.find('.coodo-selectPicker-search input').focus();
                opts.onShown.call(target);
            })
            .on("hidden.bs.dropdown", function () {
                opts.onHidden.call(target);
            })
            .on('click.selectPicker', '.coodo-selectPicker-content>ul>li', function (e) {
                var li = $(this);
                var liA = li.find('>a');
                var item = getItem(target, state.data, li.attr('itemValue'));
                if (li.hasClass('group') || li.hasClass('disabled') || li.hasClass('divider'))
                    e.stopPropagation();
                else {
                    var newValue = null;
                    var oldValue = null;
                    if (opts.multiple) {
                        newValue = [].concat(state.selectedItems, item);
                        oldValue = [].concat(state.selectedItems) || null;
                        if (li.hasClass('coodo-selectPicker-selected'))
                            unselectItem(target, li);
                        else
                            selectItem(target, li, item);
                        e.stopPropagation();
                    }
                    else {
                        newValue = [].concat(item)[0];
                        oldValue = [].concat(state.selectedItems)[0] || null;
                        if ($.inArray(item, state.selectedItems) < 0) selectItem(target, li, item);
                    }

                    if (newValue != oldValue)
                        opts.onChange.call(this, newValue, oldValue);
                }
            }) //click
            .on('keydown.selectPicker', '.coodo-selectPicker-content>ul>li', function (e) {
                var prevLi = $(this).prevAll('li:visible');
                if (e.keyCode == 38 && !prevLi.length) {
                    drop.find('.dropdown-menu>.coodo-selectPicker-search input').focus();
                    return false;
                }
            });//li key down
    }

    function loadRemoteData(target, url) {
        var opts = $.data(target, 'selectPicker').options;

        if (url) opts.url = url;

        if (opts.url)
            $.ajax({
                type: "GET",
                async: false,
                url: opts.url,
                data: "{}",
                dataType: 'json',
                success: function (data) {
                    loadData(target, data, true);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
                }
            });
    }

    function loadData(target, data, flag) {
        //falg标记参数，false不需要重构select；true重构select
        var state = $.data(target, 'selectPicker');
        if (!state) return;//dom数据已丢失，停止加载
        var opts = state.options;

        clearData(target);

        if (data && data.length) {
            if (flag) {
                $(target).children().remove();
                $.each($.grep(data, function (obj) {
                    if (!obj.divider)
                        return obj;
                }), function () {
                    $(target).append(createOption(target, this));
                    if (this.group && this.options.length) {
                        var optGroup = $('<optgroup />').attr('label', this.group);
                        $.each(this.options, function () {
                            optGroup.append(createOption(target, this));
                        });
                        $(target).append(optGroup);
                    }
                });
            }
            loadList(target, data);
            state.data = data;
        }

        opts.onLoadSuccess.call(target, data);
    }

    function createOption(target, item) {
        var opts = $.data(target, 'selectPicker').options;
        var option = $('<option />');
        var itemContent = $.extend({}, $.fn.selectPicker.itemDefaults, item);
        option.attr('value', itemContent[opts.valueField] == undefined ? itemContent[opts.textField] : itemContent[opts.valueField]);
        option.append(itemContent[opts.textField]);

        if (itemContent.selected) option.attr('selected', 'selected');
        if (itemContent.disabled) option.attr('disabled', 'disabled');

        return option;
    }

    function createView(target) {
        //var opts = $.data(target, 'selectPicker').options;
        var drop = $(target).prev('.coodo-selectPicker-list');
        if (!drop.length) {
            drop = $('<div class="dropdown btn-group coodo-selectPicker-list" />');
            var btn = $('<div class="form-control dropdown-toggle" data-toggle="dropdown" />')
                .append($('<div class="coodo-selectPicker-text"/>').attr('name', 'coodo-selectPicker-' + $(target).attr('name')))
                .append('<i class="caret coodo-selectPicker-icon"></i>')
                .appendTo(drop);
            var menu = $('<ul class="dropdown-menu" role="menu" ><li class="coodo-selectPicker-content" ><ul/></li></ul>').appendTo(drop);

            $(target).before(drop);
        }
    }

    function loadList(target, data) {
        var list = $(target).prev('.coodo-selectPicker-list').find('>ul.dropdown-menu>li.coodo-selectPicker-content>ul');

        if (list.length && data.length)
            $.each(data, function () {
                list.append(createLi(target, this));
                if (this.group && this.options.length)
                    $.each(this.options, function () {
                        list.append(createLi(target, $.extend({}, this, {isChild: true})));
                    });
            });
    }

    function createLi(target, item) {
        var state = $.data(target, 'selectPicker');
        var opts = state.options;
        var itemContent = $.extend({}, $.fn.selectPicker.itemDefaults, item);
        var li = $('<li />');
        var liA;
        var liContent;

        if (itemContent.divider)
            li.addClass('divider');
        else if (itemContent.group) {
            li.addClass('group');
            liA = $('<a href="javascript:void(0);" />').append(itemContent.group).appendTo(li);
        }
        else {
            li.attr('itemValue', itemContent[opts.valueField] == undefined ? itemContent[opts.textField] : itemContent[opts.valueField]);
            liA = $('<a href="javascript:void(0);" />').appendTo(li);
            liContent = $('<div class="coodo-selectPicker-item" />').appendTo(liA);

            if (opts.formatter) {
                var result = opts.formatter.call(this, item);
                item[opts.textField] = result;
                liContent.append(result);
            }
            else
                liContent.attr('title', itemContent[opts.textField]).append(itemContent[opts.textField]);

            if (itemContent.disabled) li.addClass('disabled');
            if (itemContent.isChild) liA.addClass('child');
            if (itemContent.selected) selectItem(target, li, item);
        }

        return li;
    }

    function selectItem(target, li, item) {
        var state = $.data(target, 'selectPicker');
        var opts = state.options;
        var itemValue = li.attr('itemValue');

        if ($.inArray(item, state.selectedItems) >= 0)
            return;

        var drop = $(target).prev('.coodo-selectPicker-list');

        if (!opts.multiple) {
            var currentItem = drop.find('.coodo-selectPicker-selected');
            if (currentItem.length) unselectItem(target, currentItem.eq(0));

            state.selectedItems[0] = item;
        }
        else
            state.selectedItems.push(item);

        //$(target).val(itemValue);
        //$(target).find('option[value=' + itemValue + '],option:contains(' + itemValue + '),optgroup>option[value=' + itemValue + '],optgroup>option:contains(' + itemValue + ')').attr("selected", 'selected');
        li.addClass('coodo-selectPicker-selected');

        opts.onSelect.call(li.children('a')[0], item); //触发选中事件
        setSelectedText(target);
    }

    function unselectItem(target, li) {
        var state = $.data(target, 'selectPicker');
        var opts = state.options;
        var selectedItems = state.selectedItems;
        var itemValue = li.attr('itemValue');
        li.removeClass('coodo-selectPicker-selected');

        $.each(selectedItems, function (i, o) {
            if (o[opts.valueField] == itemValue) {
                selectedItems.splice(i, 1);
                return false;
            }
        });

        opts.onUnselect.call(li.children('a')[0], getItem(target, state.data, itemValue)); //触发取消选中事件
        setSelectedText(target);
    }

    function setSelectedText(target) {
        var state = $(target).data('selectPicker');
        var opts = state.options;
        var selectedItems = state.selectedItems;
        var showText = "";
        var selectedValue = [];
        if (selectedItems.length)
            $.each(selectedItems, function () {
                showText += this[opts.textField] + ",";
                selectedValue.push(this[opts.valueField]);
            });
        showText = showText.substring(0, showText.length - 1);
        $(target).val(selectedValue);
        $(target).prev('.coodo-selectPicker-list').find('.coodo-selectPicker-text').html(showText);
        $(target).change();
    }

    function clearData(target) {
        var state = $.data(target, 'selectPicker');

        var drop = $(target).prev('.coodo-selectPicker-list');

        drop.find('ul.dropdown-menu>li.coodo-selectPicker-content>ul>li').remove();

        state.data = [];
        state.selectedItems = [];

        drop.find('.coodo-selectPicker-text').text('');
    }

    function createSearch(target, menuContent) {
        var opts = $.data(target, 'selectPicker').options;

        var li = $('<li class="coodo-selectPicker-search" />');
        var search = $('<div class="has-feedback" />').appendTo(li);
        var input = $('<input type="search" class="form-control" placeholder="search...." />')
            .on('input propertychange', function (e) {
                if ($.trim($(this).val()).length) {
                    searchIcon.removeClass('glyphicon-search').addClass('glyphicon-remove');
                    menuContent.find('li')
                        .show()
                        .not('li:has(a:icontains("' + $(this).val() + '"))')
                        .hide();
                }
                else {
                    searchIcon.removeClass('glyphicon-remove').addClass('glyphicon-search');
                    menuContent.find('li').show();
                }
            })
            .keydown(function (e) {
                if (e.keyCode == 40) {
                    li.next().find('ul>li:visible:eq(0)').find('a').focus();
                    return false;
                }
            })
            .appendTo(search);
        var searchIcon = $('<i class="glyphicon glyphicon-search form-control-feedback" aria-hidden="true" />').click(function (e) {
            e.stopPropagation();
            input.val('').focus().change();
            searchIcon.removeClass('glyphicon-remove').addClass('glyphicon-search');
            menuContent.find('li').show();
        }).appendTo(search);
        return li;
    }

    function getItem(target, data, idValue) {
        var opts = $(target).data('selectPicker').options;
        var result = undefined;
        var child = [];
        $.each(data, function () {
            if (this[opts.valueField] == idValue || this[opts.textField] == idValue) {
                result = this;
                return false;
            }
            else if (this.options)
                $.each(this.options, function () {
                    child.push(this);
                });
        });

        if (!result && child.length)
            return getItem(target, child, idValue);
        else
            return result;
    }

    function disabled(target) {
        var drop = $(target).prev('.coodo-selectPicker-list'); //取得下拉列表对象
        var dropToggle = drop.find('>.dropdown-toggle');

        drop.off('.dropdown .selectPicker');
        dropToggle.addClass('disabled');
    }

    function enabled(target) {
        var dropToggle = $(target).prev('.coodo-selectPicker-list').find('.dropdown-toggle');

        dropToggle.removeClass('disabled');
        initEvent(target);
    }

    $.fn.selectPicker = function (options, param) {
        if (typeof options == 'string') {
            var method = $.fn.selectPicker.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('selectPicker');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, 'selectPicker', {
                    options: $.extend({}, $.fn.selectPicker.defaults, $.parser.parseOptions(this), option),
                    data: [],
                    selectedItems: []
                });
            init(this);
        });
    };
    $.fn.selectPicker.methods = {
        options: function (jq) {
            return $.data(jq[0], 'selectPicker');
        },
        getData: function (jq) {
            return $.data(jq[0], 'selectPicker').data;
        },
        getSelected: function (jq) {
            var items = $.data(jq[0], 'selectPicker').selectedItems;
            if (items.length)
                return items[0];
            else
                return null;
        },
        getSelections: function (jq) {
            return $.data(jq[0], 'selectPicker').selectedItems;
        },
        getValue: function (jq) {
            var state = $.data(jq[0], 'selectPicker');
            var items = state.selectedItems;
            if (items.length)
                return items[0][state.options.valueField];
            else
                return null;
        },
        getText: function (jq) {
            var state = $.data(jq[0], 'selectPicker');
            var items = state.selectedItems;
            if (items.length)
                return items[0][state.options.textField];
            else
                return null;
        },
        select: function (jq, value) {
            return jq.each(function () {
                var li = $(this).prev().find('.dropdown-menu>.coodo-selectPicker-content>ul>li[itemValue="' + value + '"]');
                if (!li.length && value)
                    li = $(this).prev().find('.dropdown-menu>.coodo-selectPicker-content>ul>li:has(.coodo-selectPicker-item:contains("' + value + '"))');
                var state = $.data(this, 'selectPicker');
                if (li.length)
                    selectItem(this, li, getItem(this, state.data, value));
            });
        },
        unselect: function (jq, value) {
            return jq.each(function () {
                var li = $(this).prev().find('.dropdown-menu>.coodo-selectPicker-content>ul>li[itemValue=' + value + '],li:contains(' + value + ')');
                if (li.length)
                    unselectItem(this, li);
            });
        },
        setValues: function (jq, values) {
            return jq.each(function (i, sel) {
                $.each(values, function () {
                    $(sel).selectPicker('select', this);
                });
            });
        },
        reload: function (jq, url) {
            return jq.each(function () {
                loadRemoteData(this, url);
            });
        },
        loadData: function (jq, data) {
            return jq.each(function () {
                loadData(this, data, true);
            })
        },
        clear: function (jq) {
            return jq.each(function () {
                var state = $.data(this, 'selectPicker');
                state.selectedItems = [];
                setSelectedText(this);
                $(this).val('');
                var drop = $(this).prev();
                drop.find('.coodo-selectPicker-search input').val('');
                drop.find('li').show();
                drop.find('.coodo-selectPicker-selected').removeClass('coodo-selectPicker-selected');
            })
        },
        disabled: function (jq) {
            return jq.each(function () {
                disabled(this);
            });
        },
        enabled: function (jq) {
            return jq.each(function () {
                enabled(this);
            })
        }
    };
    $.fn.selectPicker.defaults = {
        valueField: 'id',
        textField: 'text',
        multiple: false,
        upward: false,
        data: [],
        url: undefined,
        search: false,
        width: undefined,
        height: undefined,
        tickIcon: 'glyphicon glyphicon-ok',
        formatter: undefined,
        disabled: false,
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onChange: function (newValue, oldValue) {
        },
        onSelect: function (item) {
        },
        onUnselect: function (item) {
        },
        onShown: function () {
        },
        onHidden: function () {
        }
    };
    $.fn.selectPicker.itemDefaults = {
        divider: false,
        group: undefined,
        options: undefined,
        disabled: undefined,
        selected: undefined,
        isChild: undefined
    };
}(jQuery);
//dialog
+function ($) {
    function init(target) {
        var dialog = $(target).find('>.modal-dialog');
        if (!dialog.length) {
            dialog = $('<div class="modal-dialog" role="document" />');
            var content = $('<div class="modal-content" />').appendTo(dialog);
            var header = $(target).find('.modal-header').appendTo(content);
            if (!header.length)
                header = $('<div class="modal-header" ><div class="modal-header-title" ><i /><span /></div><div class="modal-header-tool" /></div>').appendTo(content);
            var body = $('<div class="modal-body" />').appendTo(content);
            var footer = $(target).find('.modal-footer').appendTo(content);
            if (!footer.length)
                footer = $('<div class="modal-footer" />').appendTo(content);

            $(target).find('.coodo-dialog-toolbar').appendTo(footer);
        }

        if (!dialog.parent().is(target)) {
            $(target).contents().appendTo(body);
            dialog.appendTo(target);
        }

        $(target).addClass('modal coodo-dialog').attr({role: 'dialog', tabindex: '-1'});
        initAttr(target);
        initEvent(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'dialog').options;
        var dialog = $(target).find('>.modal-dialog');
        var content = dialog.find('>.modal-content');
        var header = content.find('>.modal-header');
        var headerTitle = header.find('>.modal-header-title');
        var headerTool = header.find('>.modal-header-tool');
        var body = content.find('>.modal-body');
        var footer = content.find('>.modal-footer');

        if (opts.id) {
            $(target).attr('id', opts.id);
        }
        if (opts.iconCls) {
            headerTitle.find('>i').addClass(opts.iconCls);
        }
        if (opts.title) {
            headerTitle.find('>span').html('&nbsp;' + opts.title);
        } else {
            headerTitle.addClass('hidden');
        }
        if (opts.content) {
            body.html(opts.content);
        }
        if (opts.animation) {
            $(target).addClass('fade');
        } else {
            $(target).removeClass('fade');
        }
        if (opts.maximizable) {
            if (!headerTool.find('.btn-max').length)
                $('<i class="glyphicon glyphicon-resize-full btn-max" state="normal" />').click(function () {
                    if ($(this).attr('state') == 'normal')
                        max(target);
                    else
                        restore(target);
                }).appendTo(headerTool);
        } else {
            headerTool.children('.btn-max').remove();
        }
        if (opts.closable) {
            if (!headerTool.find('>.btn-close').length)
                $('<i class="glyphicon glyphicon-remove btn-close" data-dismiss="modal" />').appendTo(headerTool);
        } else {
            headerTool.find('>.btn-close').remove();
        }
        if (opts.small) {
            dialog.addClass('modal-sm');
        } else {
            dialog.removeClass('modal-sm');
        }
        if (opts.width) {
            dialog.width(opts.width);
        }
        if (opts.height) {
            body.height(opts.height).css('overflow-y', 'auto');
        }
        if (opts.backdrop) {
            $(target).attr('data-backdrop', 'static');
        } else {
            $(target).removeAttr('data-backdrop');
        }
        if (opts.buttons) {
            footer.children().remove();
            $.each(opts.buttons, function (i, btn) {
                var button = $('<button type="button" />').appendTo(footer);
                //var btnIcon=$('<i/>').appendTo(button);
                var btnOpts = $.extend({}, $.fn.dialog.buttonDefaults, btn);

                if (btnOpts.text) button.html(btnOpts.text);
                if (btnOpts.closed) button.attr('data-dismiss', 'modal');
                if (btnOpts.btnCls) button.addClass(btnOpts.btnCls);
                if (btnOpts.iconCls) button.prepend("<i class='" + btnOpts.iconCls + "'/>");
                if (btnOpts.onClick) button.click(function () {
                    var result = btnOpts.onClick.call(this);
                    if (result || result == undefined) $(target).modal('hide');
                });
            });
        }
        if (opts.dnd) {
            content.drag({
                handle: '.modal-header>.modal-header-title',
                onDrag: function (e) {
                    var d = e.data;
                    var docW = $(window).width();
                    var docH = $(window).height();
                    d.left = d.left < 0 ? 0 : d.left;
                    d.top = d.top < 0 ? 0 : d.top;
                    /* if (d.left + d.proxy.outerWidth() > docW) {
                     d.left = docW - d.proxy.outerWidth();
                     }
                     if (d.top + d.proxy.outerHeight() > docH) {
                     d.top = docH - d.proxy.outerHeight();
                     }*/
                    var flag = docH - header.outerHeight();
                    if (d.top >= flag)
                        d.top = flag;
                }
            });
        }
    }

    function initEvent(target) {
        var opts = $.data(target, 'dialog').options;

        $(target).off('.modal')
            .on('show.bs.modal', function () {
            })
            .on('shown.bs.modal', function () {
                $(target).find('>.modal-dialog>.modal-content').resizeMask();
                opts.onShown.call(target);
            })
            .on('hide.bs.modal', function () {
            })
            .on('hidden.bs.modal', function () {
                opts.onHidden.call(target);
            });
    }

    function loadRemoteUrl(target, fnc) {
        var opts = $(target).data('dialog').options;

        var body = $(target).find('>.modal-dialog>.modal-content>.modal-body');
        var footer = $(target).find('>.modal-dialog>.modal-content>.modal-footer');
        var _url = opts.url;

        if (!_url) {
            if (fnc) fnc();
        }
        else {
            if (!opts.cache || !body.children().length) {
                if (_url.indexOf('?') >= 0)  _url += "&"; else  _url += "?";
                _url += "d=" + new Date().getTime();
                body.parent().openMask({
                    msg: opts.msg || undefined
                });
                $.ajax({
                    url: _url,
                    dataType: 'html',
                    success: function (res) {
                        var resObj = $('<div/>').append(res);
                        $.parser.parse(resObj);
                        footer.find('.coodo-dialog-toolbar').remove();
                        resObj.find('.coodo-dialog-toolbar').appendTo(footer);
                        body.html('').append(resObj.children());
                        opts.onLoaded.call(target);
                    },
                    complete: function () {
                        body.parent().closeMask();
                        if (fnc) fnc();
                    },
                    error: function () {
                        body.parent().closeMask();
                        if (fnc) fnc();
                    }
                });
            }
            else {
                if (fnc) fnc();
            }
        }
    }

    function max(target) {
        var state = $(target).data('dialog');
        var opts = state.options;
        var dialog = $(target).find('>.modal-dialog');
        var content = dialog.find('>.modal-content');
        var body = content.find('>.modal-body');

        content.find('>.modal-header>.modal-header-tool>.btn-max').attr('state', 'max').removeClass('glyphicon-resize-full').addClass('glyphicon-resize-small');

        if (!state.original)
            state.original = {
                width: opts.width || dialog.width(),
                height: opts.height || content.find('>.modal-body').outerHeight()
            };

        var w = $(window).width() * 0.98;
        var h = $(window).height() - content.find('>.modal-header').outerHeight() - content.find('>.modal-footer').outerHeight() - 65;

        if (opts.animation) {
            dialog.animate({width: w}, 100);
            body.animate({height: h}, 100);
            content.animate({top: 0, left: 0});
        }
        else {
            dialog.css({width: w});
            body.css({height: h});
        }
    }

    function restore(target) {
        var state = $(target).data('dialog');
        var opts = state.options;
        var dialog = $(target).find('>.modal-dialog');
        var content = dialog.find('>.modal-content');
        var body = content.find('>.modal-body');

        content.find('>.modal-header>.modal-header-tool>.btn-max').attr('state', 'normal').removeClass('glyphicon-resize-small').addClass('glyphicon-resize-full');

        if (state.original) {
            if (opts.animation) {
                dialog.animate({width: state.original.width}, 100);
                body.animate({height: state.original.height}, 100);
            }
            else {
                dialog.css({width: state.original.width});
                body.css({height: state.original.height});
            }
        }
    }

    $.fn.dialog = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.dialog.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('dialog');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "dialog", {
                    options: $.extend({}, $.fn.dialog.defaults, $.parser.parseOptions(this), option),
                    original: null
                });
            init(this);
        });
    };
    $.fn.dialog.methods = {
        options: function (jq) {
            return $.data(jq[0], 'dialog').options;
        },
        setTitle: function (jq, title) {
            return jq.each(function () {
                $(this).data('dialog').options.title = title;
                $(this).find('.modal-header>.modal-header-title>span').html('&nbsp;' + title);
                $(this).find('.modal-header').removeClass('hidden');
            });
        },
        open: function (jq) {
            return jq.each(function () {
                var that = this;
                loadRemoteUrl(that, function () {
                    $(that).modal('show');
                });
            });
        },
        close: function (jq) {
            return jq.each(function () {
                $(this).modal('hide');
            });
        },
        setContent: function (jq, content) {
            return jq.each(function(){
                $(this).find('.modal-body').html('');
                $(this).find('.modal-body').append(content);
            });
        }
    };
    $.fn.dialog.defaults = {
        id: undefined,
        title: undefined,
        content: undefined,
        url: undefined,
        animation: true,
        closable: true,
        iconCls: 'glyphicon glyphicon-th-large',
        small: false,
        width: undefined,
        height: undefined,
        buttons: undefined,
        backdrop: undefined,
        cache: undefined,
        dnd: undefined,
        maximizable: false,
        onShown: function () {
        },
        onHidden: function () {
        },
        onLoaded: function () {

        }
    };
    $.fn.dialog.buttonDefaults = {
        text: '', closed: false, btnCls: undefined, iconCls: undefined, onClick: function () {
        }
    }
}(jQuery);
//dialog extend
+function ($) {
    $.dialog = {
        create: function (options, target) {
            if (!options['id']) return null;
            var modal = $('#' + options.id.replace('#', ''));
            if (!modal.length)
                modal = $('<div/>').dialog(options).appendTo(target || 'body');
            else
                modal = modal.dialog(options);
            return modal;
        },
        alert: function (title, msg, fnc) {
            var alertWin = $('<div />').dialog({
                title: title, content: msg, small: true,
                backdrop: true,
                buttons: [{
                    text: '确定', closed: true, btnCls: 'btn btn-primary', onClick: function () {
                        if (fnc)
                            fnc.call(alertWin, true);
                    }
                }],
                iconCls: 'glyphicon glyphicon-warning-sign',
                onHidden: function () {
                    $(this).remove();
                }
            }).appendTo('body');
            alertWin.dialog('open')
            return alertWin;
        },
        confirm: function (title, msg, fncOK, fncCancel) {
            var confirmWin = $('<div />').dialog({
                title: title,
                width: 400,
                backdrop: true,
                buttons: [
                    {
                        text: '取消', btnCls: 'btn btn-default', close: true, onClick: function () {
                        if (fncCancel)
                            fncCancel.call(confirmWin, false);
                    }
                    },
                    {
                        text: '确定', btnCls: 'btn btn-primary', onClick: function () {
                        if (fncOK)
                            fncOK.call(confirmWin, true);
                    }
                    }
                ],
                onHidden: function () {
                    $(this).remove();
                }
            }).appendTo('body');
            $(confirmWin).dialog('setContent', msg);
            $(confirmWin).dialog('open');
            return confirmWin;
        },
        close: function (jq) {
            var target = $(jq);
            if (target.hasClass('coodo-dialog')) {
                target.dialog('close');
            }
            else {
                target.parents('.coodo-dialog:eq(0)').dialog('close');
            }
        }
    }
}(jQuery);
//autoComplete
+function ($) {
    //初始化
    function init(target) {
        createView(target);
        initAttr(target);
        initEvent(target);
    }

    // 初始化属性
    function initAttr(target) {
        var opts = $.data(target, 'autoComplete').options;
        var drop = $(target).prev('.coodo-autoComplete-list');

        if (opts.data) {
            loadData(target, opts.data);
        } else if (opts.url && !opts.async) {
            loadRemoteData(target);
        }
        if (opts.width) {
            $(target).parent().width(opts.width);
        }
        if (opts.height) {
            drop.height(opts.height);
        }
    }

    function initEvent(target) {
        var state = $.data(target, 'autoComplete');
        var opts = state.options;

        var drop = $(target).prev('.coodo-autoComplete-list');

        drop.off('.autoComplete')
            .on('click.autoComplete', 'li', function (e) {
                var item = getItem(target, $(this).attr('itemValue'));
                $(target).val($(this).find('.itemCenter').text());
                if (state.selectedItem != item) {
                    state.selectedItem = item;
                    opts.onSelect.call(this, item);
                }
            }) //click li
            .on('keydown.autoComplete', 'li', function () {
                if (e.keyCode == 38 && !$(this).prev().length) {
                    $(target).focus();
                    return false;
                }
            }); //li key down
    }

    // 加载远程数据
    function loadRemoteData(target, fnc) {
        var opts = $.data(target, 'autoComplete').options;

        var param;
        if (opts.async) param = {textVal: $(target).val()};

        $.ajax({
            url: opts.url,
            method: opts.method,
            data: param,
            dataType: 'json',
            success: function (data) {
                loadData(target, data);
                if (fnc) fnc(data);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
            }
        });
    }

    // 加载数据
    function loadData(target, data) {
        var state = $.data(target, 'autoComplete');
        if (!state) return;//dom数据已丢失，停止加载
        var drop = $(target).prev();

        cleanData(target);

        if (data && data.length) {
            $.each(data, function () {
                drop.append(createLi(target, this));
            });
            state.data = data;
        }

        state.options.onLoadSuccess.call(target, data);
    }

    // 清除数据
    function cleanData(target) {
        $(target).val('');
        $(target).prev().children().remove();
    }

    // 创建下拉视图
    function createView(target) {
        var opts = $.data(target, 'autoComplete').options;

        var region = $(target).parent('.btn-group');
        if (!region.length) {
            region = $('<div class="btn-group" style="width: 100%" />');
            $(target).before(region);
            var drop = $('<ul class="dropdown-menu coodo-autoComplete-list" />').appendTo(region);
            $(target).appendTo(region);

            $(target).attr({'data-toggle': 'dropdown', 'aria-haspopup': 'true', 'aria-expanded': 'false'})
                .addClass('coodo-autoComplete')
                .keydown(function (e) {
                    if (e.keyCode == 40) {
                        $(target).prev().find('.listItem>a:visible').eq(0).focus();
                        return false;
                    }
                })
                .on('input propertychange', function (e) {
                    if (opts.async) {
                        loadRemoteData(target, function (data) {
                            if (!data.length)
                                drop.addClass('hide');
                            else
                                drop.removeClass('hide');
                        });
                    } else {
                        filterItem(drop, $(this).val());

                        drop.removeClass('hide');
                        if (!drop.find('li:visible').length)
                            drop.addClass('hide');
                    }
                })
                .click(function (e) {
                    if ($(this).parent().hasClass('open'))
                        e.stopPropagation();
                    else {
                        if (opts.async || !opts.autoAppear)
                            drop.addClass('hide');
                        else
                            filterItem(drop, $(this).val());
                    }
                });
        }
    }

    function filterItem(drop, value) {
        if ($.trim(value).length)
            drop.find('.listItem').show().not('li:has(a:icontains("' + value + '"))').hide();
        else
            drop.find('.listItem').show();
    }

    // 创建li选项
    function createLi(target, item) {
        var state = $.data(target, 'autoComplete');
        var opts = state.options;
        var itemContent = $.extend({}, $.fn.autoComplete.itemDefaults, item);

        var li = $('<li class="listItem" />').attr('itemValue', itemContent.id || itemContent.text);
        var liContent = $('<a href="javascript:void(0);" class="text" />').appendTo(li);

        var before = $('<i class="itemBefore" />').appendTo(liContent);
        var center = $('<span class="itemCenter" />').appendTo(liContent);

        var _v = itemContent.text;
        if (itemContent.iconCls) before.addClass(itemContent.iconCls);
        if (opts.formatter) _v = opts.formatter(item);
        if (_v) center.append(_v);

        return li;
    }

    function getItem(target, idValue) {
        var state = $.data(target, 'autoComplete');
        var result = null;
        $.each(state.data, function () {
            if (this.id == idValue) {
                result = this;
                return false;
            }
        });

        return result;
    }

    $.fn.autoComplete = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.autoComplete.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('autoComplete');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "autoComplete", {
                    options: $.extend({}, $.fn.autoComplete.defaults, $.parser.parseOptions(this), option),
                    data: [],
                    selectedItem: null
                });
            init(this);
        });
    };
    $.fn.autoComplete.methods = {
        options: function (jq) {
            return $.data(jq[0], 'autoComplete').options;
        },
        getData: function (jq) {
            return $.data(jq[0], 'autoComplete').data;
        },
        loadData: function (jq, data) {
            return jq.each(function () {
                loadData(this, data);
            });
        },
        reload: function (jq) {
            return jq.each(function () {
                loadRemoteData(this);
            });
        },
        getValue: function (jq) {
            var item = $.data(jq[0], 'autoComplete').selectedItem;
            if (item)
                return item.id;
            else
                return null;
        },
        clear: function (jq) {
            return jq.each(function () {
                var state = $.data(this, 'autoComplete');
                state.selectedItem = null;
                $(this).val('');
            });
        }
    };
    $.fn.autoComplete.defaults = {
        data: undefined,
        url: undefined,
        method: 'Get',
        formatter: undefined,
        height: undefined,
        async: false,
        autoAppear: false,
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onSelect: function (item) {
        }
    };
    $.fn.autoComplete.itemDefaults = {
        id: undefined, text: '', iconCls: undefined
    };
}(jQuery);
//comboArea
+function ($) {
    function init(target) {
        $(target).addClass('coodo-comboArea');
        createInput(target);
        initAttr(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'comboArea').options;

        if (opts.width) {
            $(target).width(opts.width);
        }
        if (opts.height) {
            $(target).height(opts.height).css('overflow-y', 'auto');
        }
        if (opts.data) {
            loadData(target, opts.data);
        } else if (opts.url) {
            loadRemoteData(target);
        }
        if (opts.disabled) {
            disabled(target);
        } else {
            enabled(target);
        }
    }

    function initEvent(target) {
        var state = $.data(target, 'comboArea');
        var opts = state.options;

        $(target).off('.comboArea')
            .on('click.comboArea', function (e) {
                e.stopPropagation();
                $(this).find('.comboArea-input').focus();
            }) //make input box get focus
            .on('click.comboArea', '.areaItem', function (e) {
                e.stopPropagation();
                var item = getItem(target, $(this).attr('itemValue'));

                //onSelect event
                if (!$(this).hasClass('selectedItem') && state.selectedItem != item) {
                    $(target).find('.selectedItem').removeClass('selectedItem');
                    $(this).addClass('selectedItem');
                    state.selectedItem = item;
                    opts.onSelect.call(this, item);
                }
                opts.onClick.call(this, item);
            })//click
            .on('dblclick.comboArea', '.areaItem', function (e) {
                e.stopPropagation();
                opts.onDblClick.call(this, getItem(target, $(this).attr('itemValue')));
            }) //dblClick
            .on('click.comboArea', '.areaItem .close', function (e) {
                e.stopPropagation();
                closeData(target, $(this).parent());
            }) //close icon
            .on('focus.comboArea', '.comboArea-input', function (e) {
                $(target).addClass('editing');
            })
            .on('blur.comboArea', '.comboArea-input', function (e) {
                $(target).removeClass('editing');
            });
    }

    function loadRemoteData(target, url) {
        var opts = $.data(target, 'comboArea').options;

        if (url) opts.url = url;

        if (opts.url) {
            $.ajax({
                url: opts.url,
                method: opts.method,
                dataType: 'json',
                success: function (data) {
                    loadData(target, data);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
                }
            });
        }
    }

    function loadData(target, data) {
        var state = $.data(target, 'comboArea');
        if (!state) return;//dom数据已丢失，停止加载
        var opts = state.options;

        clearData(target);

        if (data && data.length) {
            loadComboAreaData(target, data);
            state.data = data;
        }

        opts.onLoadSuccess.call(target, data);
    }

    function loadComboAreaData(target, data) {
        $.each(data, function () {
            createItem(target, this);
        });
    }

    function createInput(target) {
        var opts = $(target).data('comboArea').options;
        //ul
        var parentItem = $(target).find('ul.comboArea-ul');
        if (!parentItem.length)
            parentItem = $('<ul class="comboArea-ul"/>').appendTo(target);
        var item = $(parentItem.find('>.areaItemOther'));
        if (!item.length)
            item = $('<li class="areaItemOther" />').appendTo(parentItem);
        if (!opts.disabledInput) {
            if (!item.find('>.comboArea-input').length) {
                var defaultSize = 8;
                $('<input class="comboArea-input" tabindex="-1" />').attr('size', defaultSize)
                    .keypress(function (event) {
                        if (event.keyCode == '13') {
                            appendItem(target, {text: $(this).val()});
                            $(this).val('').attr('size', defaultSize).focus();
                        }
                    })
                    .keydown(function (event) {
                        if (this.value.length > defaultSize)
                            $(this).attr('size', this.value.length + 3);
                        else
                            $(this).attr('size', defaultSize);
                    })
                    .blur(function () {
                        appendItem(target, {text: $(this).val()});
                        $(this).val('').attr('size', defaultSize);
                    })
                    .appendTo(item).focus();
            }
        }
        else {
            item.find('>.comboArea-input').remove();
        }
    }

    function createItem(target, item) {
        var state = $.data(target, 'comboArea');
        var opts = state.options;
        var itemData = $.extend({}, $.fn.comboArea.itemDefaults, item);
        var ulList = $(target).find('>.comboArea-ul');

        var temp = ulList.find('.areaItem .itemText:contains("' + itemData.text + '")');
        if (temp.length)
            return false;

        //li
        var liItem = $('<li class="areaItem" />').attr('itemValue', itemData.id || itemData.text)
            .insertBefore(ulList.find('.areaItemOther'));


        //itemText
        var itemText = $('<span class="itemText"/>').appendTo(liItem);

        //content
        var _v = itemData.text || "";
        if (opts.formatter) {
            _v = opts.formatter.call(itemText, _v, itemData);
        }
        itemText.append(_v);

        //icon
        if (opts.closable)  $('<i class="close">&times;</i>').appendTo(liItem);

        state.data.push(item);

        return true;
    }

    function closeData(target, iDom) {
        var state = $.data(target, 'comboArea');
        var itemValue = iDom.attr('itemValue');
        var item;
        $.each(state.data, function (index) {
            if (itemValue == (this.id || this.text)) {
                item = this;
                state.data.splice(index, 1);
                return false;
            }
        });
        iDom.remove();

        state.options.onRemove.call(target, item);
    }

    function appendItem(target, item) {
        var state = $.data(target, 'comboArea');
        if (!$.trim(item.text))
            return;
        if (createItem(target, item))
            state.options.onAppend.call(target, item);
    }

    function getItem(target, id) {
        var data = $.data(target, 'comboArea').data;
        var result = null;
        $.each(data, function () {
            if (this.id == id) {
                result = this;
                return false;
            }
        });

        return result;
    }

    function clearData(target) {
        var state = $.data(target, 'comboArea');
        state.data = [];
        $(target).find('.areaItem').remove();
        $(target).find('.areaItemOther>.comboArea-input').val('').focus();
    }

    function disabled(target) {
        $(target).off('.comboArea');
        $(target).find('>.comboArea-ul>.areaItem').off('.comboArea');
        $(target).find('>.comboArea-ul>.areaItem .close').off('.comboArea');
        $(target).find('.comboArea-input').attr('disabled', 'disabled');
        $(target).addClass('disabled');
    }

    function enabled(target) {
        $(target).removeClass('disabled');
        $(target).find('.comboArea-input').removeAttr('disabled');
        initEvent(target);
    }

    $.fn.comboArea = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.comboArea.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('comboArea');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "comboArea", {
                    options: $.extend({}, $.fn.comboArea.defaults, $.parser.parseOptions(this), option),
                    data: [],
                    selectedItem: null
                });
            init(this);
        });
    };
    $.fn.comboArea.methods = {
        options: function (jq) {
            return $.data(jq[0], 'comboArea').options;
        },
        getData: function (jq) {
            return $.data(jq[0], 'comboArea').data;
        },
        loadData: function (jq, data) {
            return jq.each(function () {
                loadData(this, data);
            });
        },
        reload: function (jq, url) {
            return jq.each(function () {
                loadRemoteData(this, url);
            });
        },
        append: function (jq, item) {
            return jq.each(function () {
                appendItem(this, item);
            });
        },
        remove: function (jq, idText) {
            return jq.each(function () {
                var target = this;
                $(this).find('.areaItem[itemValue=\'' + idText + '\'],.areaItem:has(>.itemText:contains(\'' + idText + '\'))').each(function () {
                    closeData(target, $(this));
                });
            });
        },
        clear: function (jq) {
            return jq.each(function () {
                clearData(this);
            });
        },
        disabled: function (jq) {
            return jq.each(function () {
                disabled(this);
            });
        },
        enabled: function (jq) {
            return jq.each(function () {
                enabled(this);
            });
        }
    };
    $.fn.comboArea.defaults = {
        url: undefined,
        method: 'Get',
        data: undefined,
        width: undefined,
        height: undefined,
        closable: true,
        disabledInput: false,
        formatter: undefined,
        disabled: false,
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onClick: function (item) {
        },
        onDblClick: function (item) {
        },
        onSelect: function (item) {
        },
        onAppend: function (item) {

        },
        onRemove: function (item) {

        }
    };
    $.fn.comboArea.itemDefaults = {
        id: undefined, text: ''
    };
}(jQuery);
//combo
+function ($) {
    function init(target) {
        $(target).addClass('coodo-combo');
        $(target).hide();
        createView(target);
        initAttr(target);
        initEvent(target);
    }

    function createView(target) {
        var opts = $(target).data('combo').options;
        var drop = $(target).prev('.coodo-combo-list');
        if (!drop.length) {
            drop = $('<div class="btn-group coodo-combo-list" />')
                .append('<div class="form-control coodo-combo-area" /><div class="coodo-combo-content" /><input type="hidden" class="coodo-combo-text" value=""/><input type="hidden" class="coodo-combo-value" value=""/>');
            $(target).before(drop);
        }
    }

    function initAttr(target) {
        var opts = $(target).data('combo').options;
        var _combo = $(target).prev('.coodo-combo-list');
        var _comboArea = _combo.find('>.coodo-combo-area');
        var comboContent = _combo.find('>.coodo-combo-content');
        if (opts.width) {
            _comboArea.css('width', opts.width);
        }
        if (opts.height) {
            _comboArea.css('height', opts.height);
        }
        if (opts.panelWidth) {
            comboContent.css('width', opts.panelWidth);
        }
        if (opts.panelHeight) {
            comboContent.css('max-height', opts.panelHeight);
        }
    }

    function initEvent(target) {
        $(target).prev('.coodo-combo-list').off('.combo')
            .on('click.combo', '>.coodo-combo-area', function () {
                $(this).parent().toggleClass('open');
            });

        $(document).off('.combo').on('mousedown.combo', function (e) {
            var p = $(e.target).parents('.coodo-combo-list');
            if (!p.length) {
                $('.coodo-combo-list').removeClass('open');
            }
        });
    }

    function disabled(target) {
        $(target).prev('.coodo-combo-list').off('.combo').addClass('coodo-combo-disabled');
    }

    function enabled(target) {
        $(target).prev('.coodo-combo-list').removeClass('coodo-combo-disabled');
        initEvent(target);
    }

    $.fn.combo = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.combo.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('combo');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "combo", {
                    options: $.extend({}, $.fn.combo.defaults, $.parser.parseOptions(this), option),
                    selectedItems: []
                });
            init(this);
        });
    };
    $.fn.combo.methods = {
        options: function (jq) {
            return $.data(jq[0], 'combo').options;
        },
        enabled: function (jq) {
            return jq.each(function () {
                enabled(this);
            });
        },
        disabled: function (jq) {
            return jq.each(function () {
                disabled(this);
            });
        },
        setText: function (jq, text) {
            return jq.each(function () {
                $(this).prev('.coodo-combo-list').find('>.coodo-combo-text').val(text);
            });
        },
        getText: function (jq) {
            return jq.eq(0).prev('.coodo-combo-list').find('>.coodo-combo-text').val();
        },
        setValue: function (jq, value) {
            return jq.each(function () {
                $(this).prev('.coodo-combo-list').find('>.coodo-combo-value').val(value);
            });
        },
        getValue: function (jq) {
            return jq.eq(0).prev('.coodo-combo-list').find('>.coodo-combo-value').val();
        },
        panel: function (jq) {
            return jq.eq(0).prev('.coodo-combo-list').find('>.coodo-combo-content');
        },
        textbox: function (jq) {
            return jq.eq(0).prev('.coodo-combo-list').find('>.coodo-combo-area');
        }
    };
    $.fn.combo.defaults = {
        width: undefined,
        height: undefined,
        panelWidth: undefined,
        panelHeight: undefined
    };
}(jQuery);
//comboGrid
+function ($) {
    function init(target) {
        $(target).addClass('coodo-comboGrid');
        initAttr(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'comboGrid').options;
        $(target).combo($.extend({}, opts));
        $(target).combo('textbox').addClass('coodo-comboGrid-area').empty().append('<div class="coodo-comboGrid-text"></div><i class="caret coodo-comboGrid-icon"></i>');
        $(target).combo('panel').empty().append(createTable(target).grid('getPanel'));
        $(target).prev('.coodo-combo-list').addClass('coodo-comboGrid-list');
    }

    function createTable(target) {
        var opts = $.data(target, 'comboGrid').options;
        var table = $('<table/>').grid({
            title: opts.title,
            idField: opts.idField,
            data: opts.data,
            url: opts.url,
            method: opts.method,
            queryParams: opts.queryParams,
            sortName: opts.sortName,
            sortOrder: opts.sortOrder,
            rowNumbers: opts.rowNumbers,
            singleSelect: opts.singleSelect,
            checkOnSelect: true,
            selectOnCheck: true,
            disableSelect: false,
            condensed: opts.condensed,
            loadMsg: opts.loadMsg,
            noRecordMsg: opts.noRecordMsg,
            striped: opts.striped,
            border: opts.border,
            hover: opts.hover,
            pageSize: opts.pageSize,
            pageNumber: opts.pageNumber,
            showPage: opts.showPage,
            pagination: opts.pagination,
            toolbar: opts.toolbar,
            columnChoose: opts.columnChoose,
            rowStyle: opts.rowStyle,
            columns: opts.columns,
            onLoadSuccess: function (data) {
                opts.onLoadSuccess.call(target, data);
            },
            onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
                opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
            },
            onSelect: function (rowIndex, rowData) {
                selectItem(target, rowData);
                if (opts.singleSelect) {
                    $(target).prev('.coodo-combo-list').removeClass('open');
                }
            },
            onUnselect: function (rowIndex, rowData) {
                unselectItem(target, rowData);
            }
        });
        return table;
    }

    function selectItem(target, rowData) {
        var state = $.data(target, 'comboGrid'),
            opts = state.options;
        if (opts.singleSelect) {
            if (state.selectedItems.length) {
                $(target).combo('panel').find('.fixed-table-body>.coodo-grid').grid('unselectRow', rowData[opts.idField]);
            }
            state.selectedItems[0] = rowData;
        } else {
            state.selectedItems.push(rowData);
        }
        setSelectedText(target);
        opts.onSelect.call(target, rowData);
    }

    function unselectItem(target, rowData) {
        var state = $.data(target, 'comboGrid');
        var opts = state.options;
        var newArr = $.grep(state.selectedItems, function (val) {
            if (val[opts.idField] == rowData[opts.idField] && val[opts.textField] == rowData[opts.textField]) {
                return true;
            }
        }, true);
        state.selectedItems = newArr;
        setSelectedText(target);
        opts.onUnselect.call(target, rowData);
    }

    function setSelectedText(target) {
        var state = $(target).data('comboGrid'),
            opts = state.options,
            selectedItems = state.selectedItems,
            showText = "",
            selectedValue = [];
        if (selectedItems.length)
            $.each(selectedItems, function (i, val) {
                showText += val[opts.textField] + ",";
                selectedValue.push(val[opts.idField]);
            });
        showText = showText.substring(0, showText.length - 1);
        $(target).combo('textbox').find('>.coodo-comboGrid-text').html(showText);
        $(target).combo('setValue', selectedValue);
        $(target).combo('setText', showText);
        $(target).val(selectedValue);
        $(target).change();
    }

    function selectedAndSetValue(target, value) {
        var opts = $(target).data('comboGrid').options,
            table = $(target).combo('panel').find('.fixed-table-body>.coodo-grid'),
            flag = false;
        if (!opts.singleSelect) {
            var selectRows = table.grid('getSelections');
            if (selectRows.length) {
                var newArr = $.grep(selectRows, function (val) {
                    if (val[opts.idField] == value) {
                        return true;
                    }
                });
                flag = newArr.length > 0 ? true : false;
            }
        }
        if (!flag) table.grid('selectRow', value);
    }

    $.fn.comboGrid = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.comboGrid.methods[options];
            if (method)
                return method(this, param);
            else
                return this.combo(options, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('comboArea');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "comboGrid", {
                    options: $.extend({}, $.fn.combo.defaults, $.fn.grid.defaults, $.fn.comboGrid.defaults, $.parser.parseOptions(this), option),
                    selectedItems: []
                });
            init(this);
        });
    };
    $.fn.comboGrid.methods = {
        options: function (jq) {
            return $.data(jq[0], 'comboGrid').options;
        },
        getSelections: function (jq) {
            return $.data(jq[0], 'comboGrid').selectedItems;
        },
        select: function (jq, value) {
            return jq.each(function () {
                selectedAndSetValue(this, value);
            });
        }
    };
    $.fn.comboGrid.defaults = {
        textField: undefined,
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onSelect: function (row) {
        },
        onUnselect: function (row) {
        }
    };
}(jQuery);
//comboTree
+function ($) {
    // 初始化
    function init(target) {
        $(target).addClass('coodo-comboTree');
        $(target).hide();
        initAttr(target);
    }

    function initAttr(target) {
        var opts = $.data(target, 'comboTree').options;
        $(target).combo($.extend({}, opts));
        $(target).combo('textbox').addClass('coodo-comboTree-area').empty().append('<div class="coodo-comboTree-text"></div><i class="caret coodo-comboTree-icon"></i>');
        $(target).combo('panel').empty().append(createTree(target));
        $(target).prev('.coodo-combo-list').addClass('coodo-comboTree-list');
    }

    function createTree(target) {
        var opts = $.data(target, 'comboTree').options;
        var ul = $('<ul/>').treeView({
            animation: opts.animation,
            onlyLeafCheck: opts.onlyLeafCheck,
            lines: opts.lines,
            url: opts.url,
            method: opts.method,
            icon: opts.icon,
            checkbox: opts.checkbox,
            cascadeCheck: false,
            data: opts.data,
            onLoadSuccess: function (data) {
                opts.onLoadSuccess.call(target, data);
            },
            onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
                opts.onLoadError.call(target, XMLHttpRequest, textStatus, errorThrown);
            },
            onSelect: function (node) {
                if (!opts.checkbox) {
                    selectItem(target, node);
                    $(target).prev('.coodo-combo-list').removeClass('open');
                }
            },
            onCheck: function (node, checked) {
                if (checked) {
                    selectItem(target, node);
                } else {
                    unselectItem(target, node);
                }
            }
        });
        return ul;
    }

    function selectItem(target, node) {
        var state = $.data(target, 'comboTree');
        var opts = state.options;
        if (opts.checkbox) {
            state.selectedItems.push(node);
        } else {
            if (state.selectedItems.length) {
                $(target).combo('panel').find('>.coodo-treeView').treeView('uncheck', node.id);
            }
            state.selectedItems[0] = node;
        }
        setSelectedText(target);
        opts.onSelect.call(target, node);
    }

    function unselectItem(target, node) {
        var state = $.data(target, 'comboTree');
        var opts = state.options;
        var newArr = $.grep(state.selectedItems, function (val) {
            if (val.id == node.id && val.text == node.text) {
                return true;
            }
        }, true);
        state.selectedItems = newArr;
        setSelectedText(target);
        opts.onUnselect.call(target, node);
    }

    function setSelectedText(target) {
        var state = $(target).data('comboTree'),
            opts = state.options,
            selectedItems = state.selectedItems,
            showText = "",
            selectedValue = [];
        if (selectedItems.length)
            $.each(selectedItems, function () {
                showText += this.text + ",";
                selectedValue.push(this.id);
            });
        showText = showText.substring(0, showText.length - 1);
        $(target).combo('textbox').find('>.coodo-comboTree-text').html(showText);
        $(target).combo('setValue', selectedValue);
        $(target).combo('setText', showText);
        $(target).val(selectedValue);
        $(target).change();
    }

    function multipleSelected(target, value) {
        var opts = $(target).data('comboTree').options;
        var tree = $(target).combo('panel').find('>.coodo-treeView');
        var selectRows = tree.treeView('getChecked');
        var flag = false;
        if (selectRows.length) {
            var newArr = $.grep(selectRows, function (val) {
                if (val.id == value) {
                    return true;
                }
            });
            flag = newArr.length > 0 ? true : false;
        }

        if (!flag) {
            tree.treeView('check', value);
        }
    }

    function selected(target, value) {
        var opts = $(target).data('comboTree').options;
        var panel = $(target).combo('panel');
        var li = panel.find('ul.coodoTree>li>.nodeContent[node-id="' + value + '"]');
        if (!li.length && value) {
            panel.find('ul.coodoTree>li>.nodeContent:has(.nodeTitle:contains("' + value + '"))').each(function () {
                if ($(this).find('>.nodeTitle').text() == value) {
                    li = $(this);
                }
            });
        }
        if (li.length) {
            if (opts.checkbox)
                multipleSelected(target, li.attr('node-id'));
            else
                panel.find('>.coodo-treeView').treeView('select', li.attr('node-id'));
        }
    }

    $.fn.comboTree = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.comboTree.methods[options];
            if (method)
                return method(this, param);
            else
                return this.combo(options, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('comboTree');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "comboTree", {
                    options: $.extend({}, $.fn.combo.defaults, $.fn.treeView.defaults, $.fn.comboTree.defaults, $.parser.parseOptions(this), option),
                    selectedItems: []
                });
            init(this);
        });
    };
    $.fn.comboTree.methods = {
        options: function (jq) {
            return $.data(jq[0], 'comboTree').options;
        },
        select: function (jq, value) {
            return jq.each(function () {
                selected(this, value);
            });
        },
        getSelections: function (jq) {
            return $.data(jq[0], 'comboTree').selectedItems;
        }
    };
    $.fn.comboTree.defaults = {
        onLoadSuccess: function (data) {
        },
        onLoadError: function (XMLHttpRequest, textStatus, errorThrown) {
        },
        onSelect: function (node) {
        },
        onUnselect: function (node) {
        }
    };
}(jQuery);
//layout
+function ($) {
    // 初始化
    function init(target) {
        var opts=$(target).data('layout').options;
        $(target).addClass('coodo-layout');
        initAttr(target);
        sortPanel(target);
        buildLayout(target);
        dragPanel(target);

        $(window).resize(function (e) {
            $.each($('.coodo-layout'), function () {
                var _target = $(this);
                var gpTarget = _target.parent();
                var cW = (_target.is('body') ? e.target.innerWidth|| e.target.documentElement.offsetWidth-4 : _target.width(gpTarget.width()) && gpTarget.width());
                var cH = (_target.is('body') ? e.target.innerHeight ||e.target.documentElement.offsetHeight : _target.height(gpTarget.height())&& gpTarget.height());
                resizeLayout(_target, cW, cH);
                buildDrag(_target);
                dragPanel(_target, cW, cH);
            })
        });

        opts.onReady.call(target);
    }

    function initAttr(target) {
        var opts = $(target).data('layout').options;

        if (opts.border) {
            $(target).addClass('coodo-border');
        }

        var gTarget = $(target);
        var gpTarget = gTarget.parent();
        if (!gTarget.is('body')) {
            if (getWidth(gTarget) == 0) {
                gTarget.width(gpTarget.width());
            }
            if (getHeight(gTarget) == 0) {
                gTarget.height(gpTarget.height());
            }
            gpTarget.addClass('nesting-layout');
        }
    }

    function sortPanel(target) {
        var north = $(target).children('div[region="north"]');
        var west = $(target).children('div[region="west"]');
        var center = $(target).children('div[region="center"]');
        var east = $(target).children('div[region="east"]');
        var south = $(target).children('div[region="south"]');
        $(target).prepend(south).prepend(east).prepend(center).prepend(west).prepend(north);
    }

    function dragPanel(target, cw, ch) {
        var opts = $(target).data('layout').options;
        var north = $(target).find('>div[region="north"]');
        var west = $(target).find('>div[region="west"]');
        var east = $(target).find('>div[region="east"]');
        var south = $(target).find('>div[region="south"]');
        var center = $(target).find('>div[region="center"]');

        var stepH = 0, stepW = 0, affectedEle = null, affectedSplit = null;
        var minTop = 50, minLeft = 50,
            maxH = center.outerHeight(),
            maxW = center.outerWidth();

        if (north.filter('[split="true"]').length) {
            maxH += north.outerHeight();
            var northH = north.outerHeight();
            var nSplit = $(target).find('>.north-split');
            if (!nSplit.length) {
                nSplit = $('<div class="coodo-layout-split north-split"/>').width(north.outerWidth()).height(3);
            }
            nSplit.drag({
                axis: 'v',
                cursor: 'row-resize',
                onDrag: function (e) {
                    if (e.data.top - north.offset().top < minTop) {
                        e.data.top = north.offset().top + minTop;
                    }
                    if (e.data.top - north.offset().top > (center.outerHeight() + north.outerHeight() - minTop)) {
                        e.data.top = north.offset().top + center.outerHeight() + north.outerHeight() - minTop;
                    }

                    north.css('height', e.data.top - north.offset().top);
                    stepH = e.data.top - north.offset().top - northH;
                    affectedEle = $(target).find('>div[region="west"],>div[region="center"],>div[region="east"]');
                    affectedEle.css('height', center.outerHeight() - stepH)
                    $(target).find('>.west-split').height(center.outerHeight()).offset({top: e.data.top});
                    $(target).find('>.east-split').height(center.outerHeight()).offset({top: e.data.top});
                    northH = north.outerHeight();

                    opts.onMove.call(target, north, this);
                }
            }).appendTo(target);

            nSplit.offset({left: north.offset().left, top: north.offset().top + north.height()});
        }
        if (west.filter('[split="true"]').length) {
            maxW += west.outerWidth();
            var westW = west.outerWidth();
            var wSplit = $(target).find('>.west-split');
            if (!wSplit.length) {
                wSplit = $('<div class="coodo-layout-split west-split"/>').width(3).height(west.outerHeight());
            }
            wSplit.drag({
                axis: 'h',
                cursor: 'col-resize',
                onDrag: function (e) {
                    //改变大小后重新计算
                    if (e.data.left - west.offset().left < minLeft) {
                        e.data.left = west.offset().left + minLeft;
                    }
                    if (e.data.left - west.offset().left > (center.outerWidth() + west.outerWidth() - minLeft)) {
                        e.data.left = west.offset().left + center.outerWidth() + west.outerWidth() - minLeft;
                    }

                    west.css('width', e.data.left - west.offset().left);
                    stepW = e.data.left - west.offset().left - westW;
                    center.css('width', center.outerWidth() - stepW);
                    westW = west.outerWidth();

                    opts.onMove.call(target, west, this);
                }
            }).appendTo(target);

            wSplit.offset({left: west.offset().left + west.width(), top: west.offset().top});
        }
        if (east.filter('[split="true"]').length) {
            maxW += east.outerWidth();
            var eastL = east.offset().left;
            var eSplit = $(target).find('>.east-split');
            if (!eSplit.length) {
                eSplit = $('<div class="coodo-layout-split east-split"/>').width(3).height(east.outerHeight());
            }
            eSplit.drag({
                axis: 'h',
                cursor: 'col-resize',
                onDrag: function (e) {
                    //改变大小后重新计算
                    if (cw) maxW = cw;
                    if (e.data.left < center.offset().left + minLeft) {
                        e.data.left = center.offset().left + minLeft;
                    }
                    if (e.data.left > maxW - minLeft) {
                        e.data.left = maxW - minLeft;
                    }

                    stepW = e.data.left - eastL;
                    east.css('width', east.outerWidth() - stepW);
                    center.css('width', center.outerWidth() + stepW);
                    eastL = east.offset().left;

                    opts.onMove.call(target, east, this);
                }
            }).appendTo(target);

            eSplit.offset({left: east.offset().left, top: east.offset().top});
        }
        if (south.filter('[split="true"]').length) {
            maxH += south.outerHeight();
            var southT = south.offset().top;
            var sSplit = $(target).find('>.south-split');
            if (!sSplit.length) {
                sSplit = $('<div class="coodo-layout-split south-split"/>').width(south.outerWidth()).height(3);
            }
            sSplit.drag({
                axis: 'v',
                cursor: 'row-resize',
                onDrag: function (e) {
                    //改变大小后重新计算
                    if (ch) maxH = ch;

                    if (e.data.top < center.offset().top + minTop) {
                        e.data.top = center.offset().top + minTop;
                    }
                    if (e.data.top > maxH - minTop) {
                        e.data.top = maxH - minTop;
                    }

                    stepH = e.data.top - southT;
                    south.css('height', south.outerHeight() - stepH);
                    affectedEle = $(target).find('>div[region="west"],>div[region="center"],>div[region="east"]');
                    affectedEle.css('height', center.outerHeight() + stepH);
                    $(target).find('>.west-split').height(center.outerHeight());
                    $(target).find('>.east-split').height(center.outerHeight());
                    southT = south.offset().top;

                    opts.onMove.call(target, south, this);
                }
            }).appendTo(target);

            sSplit.offset({left: south.offset().left, top: south.offset().top});
        }
    }

    function buildDrag(target) {
        var nSplit = $(target).find('>div.north-split');
        var wSplit = $(target).find('>div.west-split');
        var eSplit = $(target).find('>div.east-split');
        var sSplit = $(target).find('>div.south-split');

        if (nSplit.length) {
            var north = $(target).find('>div[region="north"]');
            nSplit.width(north.outerWidth());
            nSplit.offset({left: north.offset().left, top: north.offset().top + north.height()});
        }
        if (wSplit.length) {
            var west = $(target).find('>div[region="west"]');
            wSplit.height(west.outerHeight());
            wSplit.offset({left: west.offset().left + west.width(), top: west.offset().top});
        }
        if (eSplit.length) {
            var east = $(target).find('>div[region="east"]');
            eSplit.height(east.outerHeight());
            eSplit.offset({left: east.offset().left, top: east.offset().top});
        }
        if (sSplit.length) {
            var south = $(target).find('>div[region="south"]');
            sSplit.width(south.outerWidth());
            sSplit.offset({left: south.offset().left, top: south.offset().top});
        }
    }

    function resizeLayout(target, cw, ch) {
        var state = $(target).data('layout');

        var north = $(target).children('div[region="north"]');
        var west = $(target).children('div[region="west"]');
        var center = $(target).children('div[region="center"]');
        var east = $(target).children('div[region="east"]');
        var south = $(target).children('div[region="south"]');

        var middleW = cw;
        var middleH = ch;
        if (north.length) {
            north.outerWidth(cw);
            middleH -= north.outerHeight();
        }
        if (south.length) {
            south.outerWidth(cw);
            middleH -= south.outerHeight();
        }
        if (west.length) {
            west.outerHeight(middleH);
            middleW -= west.outerWidth();
        }
        if (east.length) {
            east.outerHeight(middleH);
            middleW -= east.outerWidth();
        }

        //center.css('width', middleW-1);
        //center.css('height', middleH);
        center.outerWidth(middleW);
        center.outerHeight(middleH);

        state.cWidth = cw;
        state.cHeight = ch;
    }

    function buildLayout(target) {
        var state = $(target).data('layout');
        var gpTarget = $(target).parent();
        var cW = ($(target).is('body') ? $(window).width() : $(target).width(gpTarget.width()) && gpTarget.width());
        var cH = ($(target).is('body') ? $(window).height() : $(target).height(gpTarget.height()) && gpTarget.height());

        var north = $(target).children('div[region="north"]').addClass('coodo-layout-north');
        var west = $(target).children('div[region="west"]').addClass('coodo-layout-west');
        var center = $(target).children('div[region="center"]').addClass('coodo-layout-center');
        var east = $(target).children('div[region="east"]').addClass('coodo-layout-east');
        var south = $(target).children('div[region="south"]').addClass('coodo-layout-south');

        //height  2:6:2
        //width   2:6:2
        var middleH = cH;
        var middleW = cW;
        var h2 = cH * 0.2;
        var w2 = cW * 0.2;

        if (north.length) {
            north.width(cW - getLRWidth(north));
            var northH = getHeight(north);
            if (northH > 0) {
                middleH -= northH;
            } else {
                north.height(h2 - getTBWidth(north));
                middleH -= h2;
            }
        }
        if (south.length) {
            south.width(cW - getLRWidth(south));
            var southH = getHeight(south);
            if (southH > 0) {
                middleH -= southH;
            } else {
                south.height(h2 - getTBWidth(south));
                middleH -= h2;
            }
        }
        if (west.length) {
            west.height(middleH - getTBWidth(west));
            var westW = getWidth(west);
            if (westW > 0) {
                middleW -= westW;
            } else {
                west.width(w2 - getLRWidth(west));
                middleW -= w2;
            }
        }
        if (east.length) {
            east.height(middleH - getTBWidth(east));
            var eastW = getWidth(east);
            if (eastW > 0) {
                middleW -= eastW;
            } else {
                east.width(w2 - getLRWidth(east));
                middleW -= w2;
            }
        }

        center.width(middleW - getLRWidth(center));
        center.height(middleH - getTBWidth(center));
        state.cWidth = cW;
        state.cHeight = cH;
    }

    function getLRWidth(target) {
        return (+target.css('border-left-width').replace('px', '') || 0) + (+target.css('border-right-width').replace('px', '') || 0);
    }

    function getTBWidth(target) {
        return (+target.css('border-top-width').replace('px', '') || 0) + (+target.css('border-bottom-width').replace('px', '') || 0)
    }

    function getWidth(target) {
        var cw = 0;
        var cStyle = target.attr('style');
        if (cStyle && cStyle.toLowerCase().indexOf('width') > -1) {
            cw = target.outerWidth();
        }
        return cw;
    }

    function getHeight(target) {
        var ch = 0;
        var cStyle = target.attr('style');
        if (cStyle && cStyle.toLowerCase().indexOf('height') > -1) {
            ch = target.outerHeight();
        }
        return ch;
    }

    function resize(target, cw, ch) {
        $(target).css({width: cw, height: ch});
        resizeLayout(target, cw, ch);
        buildDrag(target);
        dragPanel(target, cw, ch);
        $(target).find('.coodo-layout').each(function(){
            var _target = $(this);
            var gpTarget = _target.parent();
            var cW = (_target.is('body') ? e.target.innerWidth : _target.width(gpTarget.width()) && gpTarget.width());
            var cH = (_target.is('body') ? e.target.innerHeight : _target.height(gpTarget.height())&& gpTarget.height());
            resizeLayout(_target, cW, cH);
            buildDrag(_target);
            dragPanel(_target, cW, cH);
        });
    }

    $.fn.layout = function (options, param) {
        if (typeof options == "string") {
            var method = $.fn.layout.methods[options];
            if (method) return method(this, param);
        }

        var option = options || {};

        return this.each(function () {
            var state = $(this).data('layout');
            if (state)
                $.extend(state.options, option);
            else
                $.data(this, "layout", {
                    options: $.extend({}, $.fn.layout.defaults, $.parser.parseOptions(this), option),
                    cWidth: 0,
                    cHeight: 0,
                    panels: {north: $(), center: $(), west: $(), east: $(), south: $()}
                });
            init(this);
        });
    };
    $.fn.layout.methods = {
        options: function (jq) {
            return $.data(jq[0], 'layout').options;
        },
        resize: function(jq, param) {
            return jq.each(function(){
                resize(this, param.width, param.height);
            });
        }
    };
    $.fn.layout.defaults = {
        border: true,
        onMove: function (source, split) {
        },
        onReady:function(){
        }
    };
}(jQuery);